STL容器之----string的常见接口介绍及模拟实现部分接口(c++)

        前言:本篇文章的内容是关于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位置就行。

上一篇:0基础学习CSS(十四)填充


下一篇:synchronized底层是怎么通过monitor进行加锁的?