前言 在C语言中,没有专门用来表示字符串的类型。C语言的字符串是一系列以\0为结尾的字符的集合。虽然C语言为这样的字符串提供了一系列的库函数如strcpy, strcmp等等,但这些函数与
前言在C语言中,没有专门用来表示字符串的类型。C语言的字符串是一系列以’\0’为结尾的字符的集合。虽然C语言为这样的字符串提供了一系列的库函数如strcpy, strcmp等等,但这些函数与字符串这个类型是分开的,这不太符合C++中面试对象的思想,所以在C++中封装了一个string类,来帮助我们操作字符串。string该如何使用,我这里就不做赘述了,大家可以去看看官方文档呀 string - C++ Reference (cplusplus.com) string模拟实现string简单实现首先我们不考虑string类的增删查改,只是先给string类搭建一个最简单的框架出来。 和C语言中相同,为了存储一个字符串,我们的string类需要一个char*的指针来指向字符像这个对象。作为一个对象,string还需要有构造函数,析构函数和拷贝构造。
有的朋友可能会疑惑,这里的构造函数和拷贝构造函数为什么不用编译器自动生成的,直接将_str指向原本的字符串就可以了,为什么还要开辟空间呢? 这是因为我们在日常使用中,假如有两个string类 a 和 b,b是由a拷贝构造而来,一般情况下我们在修改b的同时不希望a也被改。此外,如果直接将_str指向原本的字符串会导致的问题是当 a 和 b用完被销毁时,会对同一片空间调用两次析构函数,对同一片空间释放两次。所以在这里,我们需要重新开辟一片空间来给这个string。这也就是所谓的深拷贝。 然后,为了访问string类中的元素,我们需要对运算符[]进行重载。
这样我们就实现了一个简单的string类。 string完整实现构造函数,析构函数,拷贝构造 之前我们实现的一个string类是一个最简单的string类,它没有办法进行增删查改,接下来我们就来一点一点完善它。 要实现增删查改,我们还需要两个变量,一个记录string类当前长度,一个记录string类的容量大小。加入这两个变量后,我们原本的构造函数,拷贝构造和析构函数需要发生一点点变化。
运算符重载 接下来我们来实现一下,string类的运算符。在实现运算符重载时,我们需要做的只是实现少数几个运算符即可,其他的运算符可复用前面实现的运算符来达到我们想要的效果。
string接口实现 首先是比较简单的size(),empty(),capacity(),clear()。这些接口大部分直接访问string类的成员变量就可以得到结果。
因为后面的接口大部分都需要进行空间的调整,所以首先我们将调整空间的接口,reserve和resize实现。
接下来是插入的实现,首先是push_back,这个比较简单,找到尾部进行插入即可。
接下来是insert,这个较push_back而言要麻烦一些,因为除了尾插,其他地方去插入数据你都需要挪动后面数据的位置。
写完了插入,接下来当然就是删除接口:eraser
迭代器的实现 C++中的迭代器和指针类似。为什么要有迭代器呢?因为C++中有各种各样的容器,每个容器它背后的存储方式不同,访问方式也不同,为了让使用者的使用成本降低,使大部分容器可以以相同的方式去访问,就有了迭代器的产生。 接下来我们来实现string的迭代器,其实string的迭代器就是一个指针。并不用去封装特别的东西。
部分函数优化和完善 前面在写运算符重载时,还有部分运算符未重载在此加上
同时增加拷贝构造和operator=的现代写法,之前我们写拷贝构造和operator=时都需要自己去重新开空间,那么这个活可不可以让其他人帮我做呢? 我们来看看下面这一段代码
上述代码同样可以帮我们完成拷贝构造和operator= ,原理如下: 1.首先是拷贝构造,我们在拷贝构造中使用构造函数去创建一个临时对象,这个临时对象在创建时,就帮我们开辟了空间。然后我们将临时对象和此对象的所有成员进行一个交换,这样此对象就可以接管临时对象创建的那块空间,我们的拷贝构造也就成功了 2.在operator=这,我们使用的是传值传参。好处在于由于我们的string类是自定义对象,所以在传参时会去调用拷贝构造,这样传过来的str参数也拥有了自己的空间,此时我们和拷贝构造一样,将str所开辟的那块空间接管,同时由于str是函数参数,当函数结束时,str会去调用析构函数进行一个空间释放。 完整代码
|
2022-05-14
2021-11-29
2022-04-04
2022-06-24
2021-11-25