前言:本篇文章的内容是关于STL中string的使用及模拟实现部分接口用来更好的理解string。
1:常见接口的介绍及使用例子
1.1:成员函数
1.2:迭代器(iterator)
1.3:关于capacity方面的
1.4:关于访问方面的(access)
1.5:关于修改反面的(modify)
1.6:关于查找反面的(find)
2:简单模拟实现string类(部分)
关于string类:string其实就是一个管理字符的顺序表,表示字符串的串类,默认结尾含'\0',在c语言中有许多对字符串进行操作的str函数,在c++中我们用面向对象的思想将str函数写在同一个类里面,可以更好的管理字符串。
string的本质其实是basic_string<char>模板类的别名.
在使用时我们应该:1.包含头文件 2.命名空间std的展开。
我们结合库中的string类来进行理解网站:string - C++ Reference
1.1:成员函数
构造函数: 我们重点了解红色框框中的构造函数就行.
析构函数
这个接口我们不需要自己手动调用,对象的销毁时会自动调用该函数。
因为我们内部有资源管理,所以需要我们自己写析构函数。
赋值运算符重载:两个存在的对象进行赋值,需要我们自己写该函数(深拷贝),如果不写我们在使用该操作符的时候会对同一块内存空间析构两次,会有野指针的使用。
1.2:迭代器的使用
迭代器是什么:对于迭代器的理解我们可以将它理解为一个新的类型:iterator(名字),我们在对某个对象进行遍历的时候可以使用迭代器,在string中迭代器我们就可以理解为是一个指针,下面我们就来看看它的接口把。
遍历的写法,每个容器语法都类似。
使用某个容器的迭代器时,我们需要指定时那个容器中的迭代器如:
sting::iterator, vector<int>::iterator .
1.3关于capacity方面的
resize与reserve的区别
1:reserve函数:当我们的n>capacity时,reserve就相当于扩容操作,不会初始化。不会改变size(实际元素)的个数。当我们的n<=capacity时我们的reserve相当于什么都不做。
当我们已经提前知道我们所需要多少空间了,我们可以直接使用reserve来避免,开空间的花销。
2:resize函数:当我们的n>capacity时候,首先会进行扩容,然后将size的大小改成n,多余的空间如果我们调用第二种函数,那么多余的空间会使用c来进行初始化,如果调用第一种那么多余的空间会用'\0'来进行初始化。当n<capacity&&n>size的时候就相当于直接插入数据,size等于n,当n<size的时候会直接减少实际元素(size)的个数。
总结:reserve-->只会扩容 resize -->扩容+影响数据元素的个数。不会缩小空间。
1.5(modify)
1.6find:经常使用
c_str:得到const char* 的字符串,(有些场景需要使用)。
从pos位置开始,获得len个字符。截取子串。
npos:一个无符号整型值为-1,属于静态变量,属于整个类,用来做某些函数的缺省值。
2:string类的模拟实现
首先我们先来实现构造函数。
成员变量:
思路:我们自己使用开辟n+1个空间(用来放置'\0'),将str中的内容拷贝到_str中,让空间大小也一样。
strlen:计算有效元素的个数.
这里的缺省值是为了空串的时候调用。
拷贝构造
因为这里有空间资源的使用,所以我们不能不写拷贝构造,如果不写拷贝构造,那么默认的拷贝构造就是值拷贝,当析构的时候就会出现指针的非法访问。
所以我们就得进行深拷贝:自己开辟空间,将内容拷贝到我的空间中,size与capacity都相等。
赋值运算符重载思路:与拷贝构造类似
析构函数注意:delete与new的配对
迭代器的实现:
typedef char* iterator;
typedef const char* const_iterator;
iterator begin()
{
return _str;
}
iterator end()
{
return _str + _size
}
const_iterator begin()const
{
return _str;
}
const_iterator end()const
{
return _str+_size;
}
其实迭代器在string里面就是一个char*的指针,只不过我们用typedef 封装了一下而已。
reserve函数:在c++中并没有realloc这样的函数,所以扩容就需要我们进行手动的扩容,并且n的值要大于我们开的空间。
思路:先开空间,将原来的值拷贝到现有的空间,在释放旧空间,将指针指向开辟的空间,最后将容量的大小改变即可。
c_str:直接返回地址即可。
append,+=字符串功能上实现是一致的,都是先判断空间是否够,如果不够就开辟新空间,新空间的大小计算:strlen(str)+_size,就相当于刚刚开辟足够的空间。
push_back:首先要判断空间是否足够,如果不足,我们定义一个newcapacity用来判断空间是否为第一次开辟,除了第一次给空间外,其余都是直接给原来空间的两倍。然后直接在_size位置插入数据就行,并且我们需要在最后一个元素的下一个位置给个'\0',防止打印的时候(c_str),找不到'\0'而导致的错误。
clear:只需要清空里面的元素就行,并且第一个元素等于'\0',防止遍历的时候出问题。
swap:直接交换两个对象的内容即可,可以直接复用库中的函数。
size:有效数据的个数。
capacity:实际开空间的容量。
operator[ ]:一种可读可写的运算符重载,我们只需要用引用做返回值即可。
find函数:我们直接遍历字符串就行,如果找到了返回下标,未找到就返回npos.
find字符串:我们只需要调用c语言库中strstr函数就行,因为要返回下标所以我们就用两个指针相减就得到了下标。
erase:从pos位置开始删除len个字符,当len等于npos的时侯或者len+pos大于实际元素个数时,我们只需要保留前pos-1个字符就行我们直接让pos位置为'\0'并且将size的大小改变就行。
如果只删了部分未删完,那么我们就将pos+len的内容拷贝到pos位置就行。