IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> string类的模拟实现(一)—— 构造函数(无参、拷贝等) -> 正文阅读

[C++知识库]string类的模拟实现(一)—— 构造函数(无参、拷贝等)

string类是一个存放字符串的容器,既然是容器,就有容器的容量以及实际存放的量

所以我们可以构造出一些基本的成员变量

class MyString
{
private:
	char* _str;        //存放字符串
	int _size;         //实际存放的有效字符个数
	int _capacity;     //最多可以存放的有效字符个数

};

目录

一、默认构造函数

二、参数为字符串常量的构造函数

三、拷贝构造函数

1、对象初始化

?2、浅拷贝和深拷贝

(1)? 不另外开辟空间,s3和s2共享一块空间? ? —— 浅拷贝

(2)? 另外开辟空间,s2、s3各自拥有一块空间 —— 深拷贝


一、默认构造函数

像下面这种情况会调用默认构造函数

MyString s1;

(1)?开辟一个元素的空间存放 '\0'——》占位用的

(2) 实际有效字符个数为 0

(3) 容量暂时设置为 1

//写法一:
MyString()
         :_str(new char[1]),
          _size(0),
          _capacity(0)
{
    *_str = '\0';
}

//写法二:
MyString()
{    
    _str = new char[1];            //开辟一个空间存放 '\0'
    *_str = '\0'; 

    _size = 0;                    //有效字符个数为 0
    _capacity = 0;                //最多存放的有效字符个数为0
}

二、参数为字符串常量的构造函数

但有些时候,也会输入字符串常量

MyString s2("hello,world");

基本思路依然围绕三个成员变量展开?

//写法一:
MyString(const char* str = "")
         :_str(new char[strlen(str)+1]),
          _size(strlen(str)),
          _capacity(_size)
{
    strcpy(_str,str);
}

//写法二:
MyString(const char* str = "")
{
    _size = strlen(str);                  //有效字符个数为 strlen(str)
    _capacity = _size;                    //后面可能不会新增,一次写的过多会导致空间的浪费

    _str = new char[_capacity + 1];       //分配_capacity+1个空间,多加一个空间是留给'\0'的
    strcpy(_str,str);                     //按字节把str指向的内容拷贝到_str
}

三、拷贝构造函数

使用字符串常量是一种初始化方式,那如果是使用对象初始化呢??

MyString s2("hello,world");
MyString s3(s2);                //使用对象s2,来初始化s3

1、对象初始化

s2是已经存在的对象,s3希望自己的空间大小和内容和s2完全一样

把s2成员变量的值逐一赋给s3 的成员变量,这就是对象初始化

?2、浅拷贝和深拷贝

既然是希望和 s2 一样,那就有两种方式

(1)? 不另外开辟空间,s3和s2共享一块空间? ? —— 浅拷贝

?既然是指向同一块空间,那就只需要把 s2的_str 地址赋值给 s3 的_str即可

MyString(MyString& s):_str(s._str)
{
    _size = s._size;
    _capacity = s._capacity;
}

注意:

a. 当 s3 被销毁的时候,会调用析构函数,指向的空间会被销毁

b. s3被释放时,调用一次析构函数,这个空间就被释放了,如果接下来s2调用了析构函数,那么这个空间会被释放两次,程序会崩溃

这显然不是 s2 愿意看到的,因此这里并不适合使用浅拷贝

(2)? 另外开辟空间,s2、s3各自拥有一块空间 —— 深拷贝

既然不能共享,那就另外开辟一块空间

然后把 s2成员变量的值逐一赋值给 s3 的成员变量

//这里可以使用 参数列表初始化,这样写只是为了了解步骤
MyString(MyString& s)
{
    //_str = new char[strlen(s._str) + 1];    //先开辟空间
    //strcpy(_str, s._str);                   //再拷贝内容

    //_size = s._size;
    //_capacity = s._capacity;

    //上面的写法在遇到 s3 = s3,也就是自己给自己赋值时会崩溃
    if(this != &s)
    {
        _size = s._size;
        _capacity = s._capacity;

        _str = new char[_capacity + 1];    //先开辟空间
        strcpy(_str, s._str);                   //再拷贝内容 
    }
    return *this;
}

我们发现s2 和 s3的地址不一样,s3被释放的时候,也不会影响到s2

注意:

形参必须要加引用 & ,否则会引发 拷贝构造函数的无限调用

调用拷贝构造函数的几种情况_abs(ln(1+NaN))的博客-CSDN博客当我们使用一个已经存在的对象去初始化其他对象的时候,会调用拷贝构造函数除了这种情况之外,还有哪些情况会调用拷贝构造函数??https://blog.csdn.net/challenglistic/article/details/123708019?spm=1001.2014.3001.5501

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-06 15:59:31  更:2022-04-06 16:00:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 0:08:36-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码