整体逻辑:
1、构造函数,析构函数
2、遍历,size(),operator[],迭代器iterator
3、增删查改
push_back append(串) 插入前需要检查容量,reserve() 再重载+=
insert(挪动时,size_t pos小心死循环下标为0,可以引入npos多一步判断)
erase find substr 关系运算符重载
4、流插入、流提取 利用c_str打印
5、拷贝构造、赋值运算符重载
一、构造/析构
1、构造函数
size_t len = strlen(str),避免多次strlen效率低。
构造空串时可以利用一个指向" "的指针,还可以写成全缺省。
len为0,开1个空间,把\0拷贝过去。
2、析构函数
先释放_str指向的空间,然后系统自动回收内置类型。
二、遍历相关
1、[],size()
operator[]返回的是char&,const版本可以让const对象调用,只读。
2、迭代器iterator
在string中,iterator是原生指针char*。
分别定义char*为iterator,const char* 为 const_iterator,两种迭代器是两种不同的类型。
两个begin()函数,以const为区分。
注:这里的const修饰的是string对象,是string对象是否加const,对应其调用的begin()函数是否加const
如果是s1使用cit遍历,调用的是没有const修饰的begin函数,返回的是iterator,理论上是可以修改的,但是接收的是const_iterator权限缩小,最终的效果也是没有修改。
只有当const对象s2使用cit遍历时,const对象对应const修饰的begin函数,返回的也是const_iterator,达到只读效果。
本质上,const修饰的是*this这个对象,也就是之前说过的const对象只能调用const修饰的成员函数。
三、插入系列
1、reserve
只扩大容量,不缩容。
strcpy只拷贝到第一个\0结束。
对于”hello\0world”需要用memcpy,_size+1是为了把最后的\0也拷贝过去
2、push_back
先检查是否需要扩容,容量为0时给一个初始值为4
尾插后,将原来的\0覆盖了,不要忘记再补上。
3、append
append是追加一个串,为了避免重复扩容,先算一下串的长度len(如果需要就增容)
然后将str拷贝到_str+_size后。
这里用的是char* str,所以strcpy和memcpy相同。
4、重载+=
+=一个字符,复用push_back
+=一个字符串,复用append
5、resize
调整_size并初始化,必要时也会调整_capacity
6、insert
插入一个字符c时,先检查容量。
然后从_size开始把[pos,_size]往后移一个,包括_size位置的\0
头插时,防止size_t的end越界,必须让end>pos才能进入循环
insert一个字符串时,先得到len,然后检查是否需要扩容。
然后将[pos,_size]向后移动len个单位到[pos,+len,_size+len]
最后将str全部拷贝到[pos,pos+len-1],共len个,不包含\0
也可以加上npos来判断
7、erase
第二种情况将[pos+len,_size]往前移动len个单位即可。
8、find
找某个字符c从某个位置pos出现的第一个位置
直接从pos开始遍历,找到后返回下标即可。
利用库里的strstr函数,从_str+pos的位置开始找子串s
找到返回找到的下标,没找到返回nullptr。
找到时,ptr-_str指针相减,得到之间相差的元素个数,即下标位置。
9、substr
当截取长度过长时,调整realLen为_size-pos,即截取pos后所有(不包括\0)
然后从pos位置开始截取共reaLen个字符。
10、关系运算符重载
对于<操作符,保证都在范围内比较。
比较出来大于和等于都返回false。
一直相等到一个结束,此时size()短才小于。
优化后,先利用memcmp比较size个字符得到结果
ret为0时扔比较两个的长度,不为0时看ret比较出来的结果,<0则为true
strcmp只能比较C字符串,不能比较string所有情况。如hello\0world这样中间带\0的
四、输入输出
1、c_str
返回C形式的字符串,可以直接cout打印
2、cout
[0,_size]都打印,包括其中的\0
3、cin
拿到空格和\n后才能结束循环。
五、拷贝构造/运算符重载
1、传统写法
2、现代写法
先构造出一个局部的string tmp,然后通过string中的swap函数,交换tmp和*this的成员(浅拷贝)
销毁时,局部的tmp会自动调用析构函数(*this必须先初始化一下,不能把脏数据给tmp析构)
帮忙清理资源。而*this则是一个拷贝好的string。
注:这里用的是string中的swap,浅拷贝交换它们的成员。如果用算法库中的swap,会创建出一个中间对象string,完成深拷贝,效率低。
直接拷贝构造出一个str,然后swap交换。
此时如果用算法库里的swap,会调用负值重载,导致栈溢出。
3、写时拷贝
只读时,为浅拷贝,地址相同。
修改时,引用计数-1,重新开空间完成一次深拷贝
引用计数为1时才析构,平时计数-1.
目录
整体逻辑:
一、构造/析构
1、构造函数
2、析构函数
二、遍历相关
1、[],size()
编辑 2、迭代器iterator
三、插入系列
1、reserve
2、push_back
3、append
4、重载+=
5、resize
6、insert
7、erase
8、find
9、substr
10、关系运算符重载
四、输入输出
1、c_str
2、cout
3、cin
编辑 五、拷贝构造/运算符重载
1、传统写法
2、现代写法文章来源:https://www.toymoban.com/news/detail-542512.html
3、写时拷贝 文章来源地址https://www.toymoban.com/news/detail-542512.html
到了这里,关于string模拟实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!