🔥博客主页:小王又困了
📚系列专栏:C++
🌟人之为学,不日近则日退
❤️感谢大家点赞👍收藏⭐评论✍️
目录
一、存储结构
二、默认成员函数
📒2.1构造函数
📒2.2析构函数
📒2.3拷贝构造
📒2.4赋值重载
三、容量操作
📒3.1获取有效字符长度
📒3.2获取对象空间大小
📒3.3使用reserve扩容
四、字符串的遍历
📒4.1下标访问
📒4.2迭代器访问
五、修改操作
📒5.1尾插字符
📒5.2尾插字符串
📒5.3任意位置插入字符
📒5.4任意位置插入字符串
📒5.5+=重载
六、其他操作
📒6.1删除操作
📒6.2查找操作
📒6.3交换操作
📒6.4获取字符串
📒6.5运算符重载
📒6.6清理字符串
📒6.7流操作
🗒️前言:
在上一篇中我们对string类进行了简单的介绍,介绍了各个接口的作用和使用方法,今天我们将为大家介绍string常用接口的模拟实现。
一、存储结构
string本质上是一个char类型的顺序表,所以结构上和顺序表类似。
namespace bit
{class string{public:private:char* _str;size_t _size;size_t _capacity;const static size_t npos;};
}
结构上使用命名空间 bit 进行封装,防止与库冲突,其中:
- _str :指向存放字符串存空间的指针
- _size :表示当前所存储的有效字符个数
- _capacity :表示当前可存储的最大容量
- nops:此值设置为 -1,无符号整型转换就是42亿,且此值为const和静态参数具有全局效应,这个值常常被用来当作循环结束判断条件和查找时未找到的标志,某些函数设置其为缺省参数。
nops的初始化:
#include"string.h"namespace bit {const size_t string::nops = -1; }
小Tips:我们使用声明与定义分离实现,nops只能在CPP文件中定义,因为类里面的静态成员变量相当于全局变量,在.h文件中定义会出现链接错误。我们还要通过类名::成员(函数/变量) 定义和实现函数!
二、默认成员函数
📒2.1构造函数
string.h
string(const char* str = ""); //给缺省值 构造空串string.cpp
string::string(const char* str):_size(strlen(str))
{_str = new char[_size + 1];_capacity = _size;strcpy(_str, str);
}
构造函数的思路:
- 构造函数可以接收字符串,如果没有参数,默认构造一个空串
- 通过strlen先计算出字符串的长度,并通过初始化列表初始化_size
- 使用new开辟空间,这里我们要多开一个空间存放‘\0’
- 最终将字符串中的字符拷贝到我们所开的空间中
小Tips:因为_size的大小没有包含‘\0’,所以我们要多开辟一个空间。
📒2.2析构函数
我们开辟内存是使用 new[ ] 申请的,所以对应使用 delete[ ]释放。
string::~string()
{delete[] _str;_str = nullptr;_size = _capacity = 0;
}
📒2.3拷贝构造
拷贝构造函数,如果我们不写,编译器会默认生成一个,但是默认生成的拷贝构造函数只支持浅拷贝,新构造的对象只是拷贝了_str的指针地址,两个对象都指向同一块空间,最终两个对象析构时释放同一片空间的资源势必会导致程序崩溃!
我们需要新构造的对象通过拷贝构造开辟一片新的空间将数据复制过去,也就是深拷贝,需要我们自己写一个拷贝构造。
🌟传统写法:
string::string(const string& s) {_str = new char[s._size + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity; }