提要,由于string的成员函数及其用法太多,所以作者只调出了一些比较常用的函数进行讲解,而且知识点之间的关联性比较弱,文章看起来感觉这一块那一块的看着比较乱,如有问题欢迎大家指出。
一、什么是STL
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。
二、STL六大组件
其中,我们最常用的是算法和容器(数据结构部分)。
三、string类
1.string学习的意义
string翻译过来就是串(字符串)的意思,我们在c语言中也学过什么是字符串,那为什么要单拿出来系统学习呢?C语言中,字符串是以'\0'结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP(面向对象编程)的思想,而且底层空间需要用户自己管理,稍不留神可能还会越界访问。
2.string类的各功能的函数
string类的成员函数有一百多个,我们就挑其中重要性和常用性比较高的拿出来具体讲解。
(1)构造函数:与我们在类与对象中的构造函数用法相同,以下两种都是进行初始化的办法。
(2)同样,拷贝构造也一样,我们就不多说了。
(3)特别的是,string支持直接cout和cin,因为它的内部已经流插入和流提取的重载,可以直接用,方便了许多。
回顾一下之前的内容,虽然二者结果是一样的,但上面是构造,而下面是隐式类型转换,而编译器对下面的进行了优化, 所以也是构造了。(隐式类型转换如果是引用前面要加const)
3.字符串的遍历(获取字符串的长度)——operator[]重载的实现
这里我们就需要抛弃以前的语法了,比如用strlen求。惊喜的是,string类也有类似的重载,我们直接调用其内部函数即可。同样的,我们想依次打印每一个字符,只需用上面的知识加for循环就够了,我们在下面就统一展示了
这里有人或许会考虑由于i过大而越界的问题,如果我们具体实现[]运算符的重载,会发现里面是有assert断言的,就是防止访问越界,这也是string类比之前学的字符串的优点之一。(注释行与上一行等价)而且,我们也能对其字符串进行修改(如果把s3.s4放在上面的test函数也可以,因为这里传的是引用,也就引出了我们的引用的第二个优点,就是能修改返回对象,还是那句话,如果是隐式类型转换或者加了const就不能修改了)
4.字符串的遍历2——迭代器
啥叫迭代器?迭代器(iterator),属于类域里面的关键字,我们先来看他的用法
在讲迭代器之前,我们先来看看这个begin和end函数是啥东西。begin是返回开始位置的迭代器,end是返回结束位置的下一个位置的迭代器。他们都是string类的成员函数。我们暂且把迭代器看成像指针一样的东西去理解。这样上面的代码就好理解了。(迭代器不一定是指针,只是现在为了理解把它当成指针)
5字符串的遍历3——auto+for爽歪歪(它的底层其实也是迭代器)
我前面的文章有讲到auto的基本用法,需要的小伙伴自行查看哦。
6.迭代器的版本
迭代器也有const版本和非const版本,如果我们在某个string类前加const修饰,就不能用第二种方式遍历字符串了。
当程序运行时,它会调下面的const版本,返回const_iterator。为什么不是const iterator呢?
正常的迭代器是可读可写的(int*),const_iterator只读不写(迭代器指向的内容不可写,类似const int*),也就是可以遍历但不能修改指向的内容,const iterator是迭代器本身不能写(int*const)。我们如果在上图iterator前加const,那么while循环的第一行就会报错而第三行不会。
7.反向迭代器
听着名字就感觉他是用来反过来用的,实际上确实,它是用来倒着遍历的。成员函数名是rbegin和rend
此时的++就是倒着走(--的效果)。同理,反向迭代器也有const和非const版本。
接下来我们介绍几个关于string中修改功能的成员函数
1.push_back:也就是在原来的字符串后再添加字符或字符串
2.append(附加):这个和push_back基本一样。
以上函数用法都是 变量.函数名(“字符或字符串”)
不过最好用的还得看运算符重载,在string中将+=也实现了重载,如果我们要把s2的字符串加到s1后面,直接s1+=s2即可。且这种方法相比于上面两个很常用,上面的了解即可。
3.insert :插入字符串,有以下几种用法,分别是插单个字符和字符串
第二个和第三个等价,(函数中括号中第一个参数是插入的位置)我们发现插入一个字符时候还需要指明数量,造成了麻烦,所以我们平常不常用。 在实践中需求并不高。
4.erase:删除函数(与insert一样,慎用效率不高)
用法:变量.erase(开始删除的位置,删除字符的个数)或者只传一个参数,那么此时就是删除这个位置后的所有字符。
5.replace:替换函数
用法 变量.replace(从该位置开始替换,替换字符的个数,替换的内容)
以上就是常见的修改函数,我们下面看看它的容量方面的函数
1.reserve:用来改变capacity(扩容),用法:变量.reserve(你要预计开的空间大小),它只能改变该字符串空间的capacity,并不能改变size,这与我们前面提到的string类比c的优越性中assert判断越界相关了,我们在修改(增删查改)字符串时候都需要判断是否越界,此时是用size判断而不是capacity。
2.resize:这个函数就便于访问开辟空间的位置,它改变的是size,用法变量.resize(开辟空间数,每个空间的初始化)。若不传第二个参数,那么就初始化为默认字符('\0'),但它有时候也会改变capacity,
这里就是相当于扩容了,既要改变size又改变capacity,上面这个就是在原有基础上再补x,不会删除原来的内容,同时它也会缩容,既如果给一个小的resize它会删除部分内容。
以上就是有关类相关比较常用的函数,其实还有一小部分,作者打算留在下篇文章进行收尾,然后我们下期内容主要侧重于string类的底层实现。