当前位置: 首页 > news >正文

C++初阶学习第七弹——探索STL奥秘(二)——string的模拟实现

标准库中的string:C++初阶学习第六弹——string(1)——标准库中的string类-CSDN博客

前言:

在前面我们已经学习了如何使用标准库中的string类,但作为一个合格的程序员,我们不仅要会用,还要知道如何实现string中的类函数等内容,今天我们就来讲解一下string的模拟实现

目录

一、string类的构造

二、string类的拷贝构造

三、string类的析构函数

四、string类的运算符重载

1、operator=的传统写法

2、operator=的现代写法

五、代码实例

六、总结


string的模拟实现中最重要的就是string类的构造、拷贝构造、赋值运算符重载以及析构函数

接下来我们就围绕这些重点进行学习

一、string类的构造

首先我们要清楚string类在底层实际上就是一个字符指针和许多类函数,所以它的类成员变量就是:

private:char* _str;

我们先把模拟构造给出来再来讲解:

//为了区分标准库,我们用String
class String
{
public:String(const char* str = ""){if (str == nullptr){assert(false);return;}_str = new char[strlen(str) + 1];strcpy(_str, str);}void String_print(){cout << _str << endl;}
private:char* _str;
};
int main()
{String s1("abc");s1.String_print();return 0;
}

运行结果:

相信一定有细心的朋友已经注意到我们在给参数时并没有给任何东西,原因如下:

还有一点需要注意的是:我们在赋值时是创建一个新空间来储存,并不是直接赋值,这就涉及深拷贝的问题了,在下面我们讲拷贝构造的时候能更清晰的体现出来

二、string类的拷贝构造

模拟实现的代码如下:

    String(const String& s): _str(new char[strlen(s._str) + 1]){strcpy(_str, s._str);}

在这里我们主要来讲解一下深拷贝和浅拷贝的问题,我们放在一个完整的代码实例:

class String
{
public:String(const char* str = ""){if (str == nullptr){assert(false);return;}_str = new char[strlen(str) + 1];strcpy(_str, str);}String(const String& s): _str(new char[strlen(s._str) + 1]){strcpy(_str, s._str);}void String_print(){cout << _str << endl;}
private:char* _str;
};
int main()
{String s1("abc");s1.String_print();String s2(s1);s2.String_print();return 0;
}

运行结果:

错误示范:

三、string类的析构函数

由于string类对象不管以哪个方式创建时,都需要用new来开辟空间,所以string的析构函数写法为:

    ~String(){if (_str)     //检查一下_str是否为空,如果为空就不用再释放空间了{delete[] _str;_str = nullptr;}}

四、string类的运算符重载

string类的运算符重载整体来说没啥难度,在这里我们也不做过多讲解,重点来讲解一下operator=的两种写法

1、operator=的传统写法

    String& operator=(const String& s){if (s._str != _str){char* ptr = new char[strlen(s._str) + 1];    //+1是因为要多开辟一个空间存放\0strcpy(ptr, s._str);delete _str;                              //清空_str中可能有的数据_str = ptr;}return *this;}

2、operator=的现代写法

String& operator=(String s)
{swap(_str, s._str);   //swap函数算法库中存在,所以可以直接使用return *this;
}

单从篇幅上来比较,现代写法要比传统写法精简的多,那么它们两个究竟是如何实现它们的功能的呢?我们看下面的分析:

· 传统写法:

传统写法函数的参数是后值的引用,我们通过创建一个新的字符指针,并开辟空间接受后值,再把这个新创建的指针的地址传给我们的对象,从而实现了operator=的功能

· 现代写法:

现代写法则聪明的使用了算法库中的swap函数,从而让函数达到一个很精简的效果,该函数的参数是后值的临时拷贝,本来就是深拷贝,所以通过swap交换即可

传统写法和现代写法的过程比较:

五、代码实例

//为了区分标准库,我们用String
class String
{
public:String(const char* str = ""){if (str == nullptr){assert(false);return;}_str = new char[strlen(str) + 1];strcpy(_str, str);}String(const String& s): _str(new char[strlen(s._str) + 1]){strcpy(_str, s._str);}//现代写法String& operator=(String s){swap(_str, s._str);return *this;}传统写法//String& operator=(const String& s)//{//    if (s._str != _str)//    {//        char* ptr = new char[strlen(s._str) + 1];    //+1是因为要多开辟一个空间存放\0//        strcpy(ptr, s._str);//        delete _str;                              //清空_str中可能有的数据//        _str = ptr;//    }//    return *this;//}void String_print(){cout << _str << endl;}~String(){if (_str)     //检查一下_str是否为空,如果为空就不用再释放空间了{delete[] _str;_str = nullptr;}}
private:char* _str;
};
int main()
{String s1("abc");s1.String_print();String s2(s1);s2.String_print();String s3 = s2;s3.String_print();return 0;
}

运行结果:

六、总结

以上就是string模拟实现的比较重要的部分,其他类函数我们并没有写出来,但难度都不大,感兴趣的老铁可以自己摸索一下或者在网上搜一下它的实现

感谢各位大佬观看,创作不易,还请一键三连!!!

相关文章:

C++初阶学习第七弹——探索STL奥秘(二)——string的模拟实现

标准库中的string&#xff1a;C初阶学习第六弹——string&#xff08;1&#xff09;——标准库中的string类-CSDN博客 前言&#xff1a; 在前面我们已经学习了如何使用标准库中的string类&#xff0c;但作为一个合格的程序员&#xff0c;我们不仅要会用&#xff0c;还要知道如…...

5.nginx常用命令和日志定时切割

一. nginx常用的相关命令介绍 1.强制关闭nginx: ./nginx -s stop 2.优雅的关闭nginx: ./nginx -s quit 3.检查配置文件是否正确&#xff1a; ./nginx -t 4.查看nginx版本&#xff1a; ./nginx -v 5.查看nginx版本相关的配置环境信息&#xff1a;./nginx -V 6.nginx帮助信…...

Redis-详解(基础)

文章目录 什么是Redis&#xff1f;用Redis的特点&#xff1f;用Redis可以实现哪些功能&#xff1f;Redis的常用数据类型有哪些?Redis的常用框架有哪些?本篇小结 更多相关内容可查看 什么是Redis&#xff1f; Redis&#xff08;Remote DictionaryServer&#xff09;是一个开源…...

记录minio的bug(Object name contains unsupported characters.)

场景是我将后端服务从121.xxx.xxx.xxx服务器上转移到了另一台服务器10.xxx.xxx.xxx 但图片都还在121.xxx.xxx.xxx服务器上&#xff0c;同样我10.xxx.xxx.xxx也安装了minio并且我的后端服务配置的minio地址也是10.xxx.xxx.xxx 此时有一个业务通过minio客户端获取图片&#xf…...

【嵌入式开发 Linux 常用命令系列 7.6 -- sed 替换指定字符串】

请阅读【嵌入式开发学习必备专栏】 文章目录 sed 替换指定字符串 sed 替换指定字符串 背景&#xff1a; 找到当前目录下所有的.h 和 .c 文件 将他们中的字符 print_log替换为 demo_log 可以使用find命令结合sed命令在Linux环境下完成这项任务。下面是一个命令行示例&#xff…...

C++语言的字符数组

存放字符数据的数组是字符数组&#xff0c;字符数组中的一个元素存放一个字符。字符数组具有数组的共同属性。 1. 声明一个字符数组 char c[5]; 2. 字符数组赋值方式 &#xff08;1&#xff09;为数组元素逐一赋值 c[0]H c[1]E c[2]L c[3]L c[4]O &#xff08;2&…...

24届电信红队实习生面经

sql注入的一些&#xff1a;原理、打的靶场的常见绕过、问了一些函数 (load_file、 outfile这些&#xff09;、后利用 (mysql的udf提权的原理、条件、利用、其他像mssql这些数据库的提权手段、这些就没细问了&#xff0c; 就问有哪些方式&#xff1b; 问了有没有实战遇到mysql的…...

linux下使用jexus部署aspnet站点

1.运行环境 Centos 7 安装dos2unix工具 yum install dos2unix 安装jexus curl https://jexus.org/release/x64/install.sh|sudo sh2.网站部署 2.1. 将windows下的网站发布包Msc_qingdao_admin.zip上传到linux中&#xff0c; 然后解压后放入/var/www(没有则创建)目录下 r…...

代码随想录训练营Day 27|理论基础、力扣 77. 组合

1.理论基础 题目链接/文章讲解&#xff1a;代码随想录 视频讲解&#xff1a;带你学透回溯算法&#xff08;理论篇&#xff09;| 回溯法精讲&#xff01;_哔哩哔哩_bilibili 来自代码随想录的网站&#xff1a; void backtracking(参数) {if (终止条件) {存放结果;return;}for (…...

Spring框架深度解析:打造你的Java应用梦工厂

想要在Java企业级应用开发中大展身手&#xff1f;Spring框架的核心容器是你不可或缺的伙伴&#xff01; 文章目录 一. 引言1.1 介绍Spring框架的重要性1.2 阐述核心容器在Spring框架中的作用1.3 故事开端 二. 背景介绍2.1 描述Spring框架的发展历程2.2 概述Spring框架的主要特点…...

Python 正则表达式(一)

文章目录 概念正则函数match函数正则表达式修饰符意义&#xff1a; 常用匹配符限定符原生字符串边界字符 概念 正则表达式是对字符串操作的一种逻辑公式&#xff0c;就是用事先定义好的一些特定字符、及这些特定字符的组合&#xff0c;组成一个“规则字符串”&#xff0c;这个…...

Cocos Creator 3.8.x报错:5302

在小游戏加载某个bundle后&#xff0c;如果报以下错误&#xff1a; 5302&#xff1a;Can not find class %s 说明bundle中某个预制件*.prefab引用了未加载的bundle的资源。 解决方法有两个&#xff1a; 1、将引用的资源移到预制件*.prefab相同的bundle下&#xff1b; 2、将…...

网页如何集成各社区征文活动

Helllo , 我是小恒 由于我需要腾讯云社区&#xff0c;稀土掘金以及CSDN的征文活动RSS&#xff0c;找了一下没发现&#xff0c;所以使用GET 请求接口对网页定时进行拉取清洗&#xff0c;甚至无意间做了一个简单的json格式API 最终网址:hub.liheng.work API:http://hub.liheng.wo…...

【知识碎片】2024_05_13

本文记录了两道代码题【自除数】和【除自身以外数组的乘积】&#xff08;利用了前缀积和后缀积&#xff0c;值得再看&#xff09;&#xff0c;第二部分记录了关于指针数组和逗号表达式的两道选择题。 每日代码 自除数 . - 力扣&#xff08;LeetCode&#xff09; /*** Note: T…...

Day53代码随想录动态规划part13:300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组

Day52 动态规划part13 300.最长递增子序列 leetcode链接&#xff1a;300. 最长递增子序列 - 力扣&#xff08;LeetCode&#xff09; 题意&#xff1a;给你一个整数数组 nums &#xff0c;找到其中最长严格递增子序列的长度。子序列是由数组派生而来的序列&#xff0c;删除&a…...

自己动手为wordpress注册一个Carousel轮播区块

要为WordPress注册一个Carousel轮播区块&#xff0c;你可以创建一个自定义Gutenberg块。以下是一个简单的示例&#xff0c;说明如何创建一个Carousel轮播区块&#xff1a; 1. 在你的主题目录中创建一个名为carousel-block的子文件夹。在这个文件夹中&#xff0c;创建一个名为c…...

基于Springboot的实习生管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的实习生管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&a…...

良心实用的电脑桌面便利贴,好用的便利贴便签小工具

在日常办公中&#xff0c;上班族经常需要记录临时任务、重要提醒或者突发的灵感。比如&#xff0c;在紧张的项目会议中&#xff0c;忽然想到一个改进的点子&#xff0c;或者是在处理邮件时&#xff0c;需要记下对某个客户的回复要点。在这些场景下&#xff0c;如果能直接在电脑…...

Eayswoole 报错 crontab info is abnormal

在执行一个指定的定时任务时 如 php easyswoole crontab show 报错 crontab info is abnormal 如下图所示&#xff1a; 查询了半天 修改了如下配置&#xff1a; 旧的 // 创建定时任务实例 $crontab new \EasySwoole\Crontab\Crontab($crontabConfig); 修改后&#…...

移动 App 入侵与逆向破解技术-iOS 篇

如果您有耐心看完这篇文章&#xff0c;您将懂得如何着手进行app的分析、追踪、注入等实用的破解技术&#xff0c;另外&#xff0c;通过“入侵”&#xff0c;将帮助您理解如何规避常见的安全漏洞&#xff0c;文章大纲&#xff1a; 简单介绍ios二进制文件结构与入侵的原理介绍入…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用&#xff1a;实现组件通用属性的渐变过渡效果&#xff0c;提升用户体验。支持属性&#xff1a;width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项&#xff1a; 布局类属性&#xff08;如宽高&#xff09;变化时&#…...

论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)

笔记整理&#xff1a;刘治强&#xff0c;浙江大学硕士生&#xff0c;研究方向为知识图谱表示学习&#xff0c;大语言模型 论文链接&#xff1a;http://arxiv.org/abs/2407.16127 发表会议&#xff1a;ISWC 2024 1. 动机 传统的知识图谱补全&#xff08;KGC&#xff09;模型通过…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决

Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中&#xff0c;新增了一个本地验证码接口 /code&#xff0c;使用函数式路由&#xff08;RouterFunction&#xff09;和 Hutool 的 Circle…...

jmeter聚合报告中参数详解

sample、average、min、max、90%line、95%line,99%line、Error错误率、吞吐量Thoughput、KB/sec每秒传输的数据量 sample&#xff08;样本数&#xff09; 表示测试中发送的请求数量&#xff0c;即测试执行了多少次请求。 单位&#xff0c;以个或者次数表示。 示例&#xff1a;…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

安卓基础(Java 和 Gradle 版本)

1. 设置项目的 JDK 版本 方法1&#xff1a;通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分&#xff0c;设置 Gradle JDK 方法2&#xff1a;通过 Settings File → Settings... (或 CtrlAltS)…...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用

前言&#xff1a;我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM&#xff08;Java Virtual Machine&#xff09;让"一次编写&#xff0c;到处运行"成为可能。这个软件层面的虚拟化让我着迷&#xff0c;但直到后来接触VMware和Doc…...

java高级——高阶函数、如何定义一个函数式接口类似stream流的filter

java高级——高阶函数、stream流 前情提要文章介绍一、函数伊始1.1 合格的函数1.2 有形的函数2. 函数对象2.1 函数对象——行为参数化2.2 函数对象——延迟执行 二、 函数编程语法1. 函数对象表现形式1.1 Lambda表达式1.2 方法引用&#xff08;Math::max&#xff09; 2 函数接口…...

Docker、Wsl 打包迁移环境

电脑需要开启wsl2 可以使用wsl -v 查看当前的版本 wsl -v WSL 版本&#xff1a; 2.2.4.0 内核版本&#xff1a; 5.15.153.1-2 WSLg 版本&#xff1a; 1.0.61 MSRDC 版本&#xff1a; 1.2.5326 Direct3D 版本&#xff1a; 1.611.1-81528511 DXCore 版本&#xff1a; 10.0.2609…...