C++STL简介与string类¶
约 5571 个字 1098 行代码 11 张图片 预计阅读时间 32 分钟
STL简介¶
STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架
STL的版本¶
-
原始版本
Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP 版本--所有STL实现版本的始祖。
-
P. J. 版本
由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异。
-
RW版本
由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般。
-
SGI版本
由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。
STL的六大组件¶
Note
在上面的图中,空间配置器实际上就是在内存池中申请空间。另外,string
类型本不属于STL
,因为出现得早,没被划分到STL
中,但是其接口基本上和STL
中其他容器的接口类似,故将其列入上图中的STL
容器部分
string类¶
在C语言中,字符串是以'\0'
结尾的字符数组,为了操作方便,C语言还提供了和字符串相关的函数放在string.h
中,但是在C语言中,函数和字符串类型是分割的,不符合面向对象编程的思想,并且在操作字符串的过程中还需要注意防止越界
标准库中的string类¶
- 字符串是表示字符序列的类
- 标准的字符串类提供了对此类对象的支持,其接口类似于标准字符容器的接口,但添加了专门用于操作
- 单字节字符字符串的设计特性
string
类是使用char
即作为它的字符类型,使用它的默认char_traits
和分配器类型(关于模板的更多信息,请参阅basic_string
)string
类是basic_string
模板类的一个实例,它使用char
来实例化basic_string
模板类,并用char_traits
和allocator
作为basic_string
的默认参数(根于更多的模板信息请参考basic_string
)- string本质上是以字符作为元素的vector特化版本;不存在0字符结尾这个概念,能装入
\0
这种数据
Note
关于string是否可以存储\0
可以参考下面的代码演示结果:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
上面的代码中使用了原始字符串
Note
注意,string类独立于所使用的编码来处理字节:如果用来处理多字节或变长字符(如UTF-8)的序列,这个类的所有成员(如长度或大小)以及它的迭代器,将仍然按照字节(而不是实际编码的字符)来操作。
总结:
string
是表示字符串的字符串类- 该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作
string
的常规操作。 string
在底层实际是:basic_string
模板类的别名,typedef basic_string<char, char_traits, allocator> string
;- 不能操作多字节或者变长字符的序列。
Note
在使用string
类时,必须包含#include
头文件以及using namespace std;
(或者展开需要使用的内容)
string类的常用接口¶
构造函数 | 函数原型 |
---|---|
无参构造函数 | string(); |
拷贝构造函数 | string (const string& str); |
子串构造函数 | string (const string& str, size_t pos, size_t len = npos); |
使用字符串构造函数 | string (const char* s); |
使用部分字符串构造函数字符 | string (const char* s, size_t n); |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
|
Note
对于函数string (const string& str, size_t pos, size_t len = npos);
来说,pos
为起始位置,len
为需要取的字符串的长度,如果len
参数大于字符串的可提供的长度,那么会一直取到字符串结尾;如果使用缺省值npos
(缺省值为-1
),那么同样会取到字符串结尾
string
类也有析构函数~string()
和赋值运算符重载函数
赋值运算符重载函数 |
---|
string& operator= (const string& str); (对象赋值) |
string& operator= (const char* s); (字符串赋值) |
string& operator= (char c); (字符赋值) |
string类对象对容量的操作¶
函数 | 功能 |
---|---|
size() | 返回字符串有效字符长度 |
length() | 返回字符串有效字符长度 |
capacity() | 返回当前为字符串开辟的空间大小 |
reserve() | 为字符串预留指定的空间 |
resize() | 将有效字符的个数修改成指定个数,多出的空间默认使用\0填充,也可以使用指定字符填充 |
size()
函数与length()
函数¶
Note
对于计算字符串有效字符长度的函数来说不会计算'\0'
,并且size()
和length()
的效果相同
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
capacity()
函数¶
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
在上面的代码中,size()
和capacity()
并不相等,所以size()
不等同于capacity()
,可以类比到数据结构中顺序表的有效数据个数size
和capacity
capacity
的扩容方式¶
在VS环境下面,运行下面的代码可以大致估算得到capacity
的扩容倍数
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
Note
计算capacity
时不会计算\0
所存在的空间
在上面的代码中,因为并没有计算\0所在的空间,所以实际结果为:
C++ | |
---|---|
1 2 3 4 5 6 |
|
观察到,除了第一次和第二次以外,其余均为大致1.5倍增长,但是第一次和第二次的增长并不是2倍,而是因为VS将第一次存储字符串的位置分成了两部分,第一个部分是_buf[16]
数组,第二个部分是*ptr
,指向超过16个字符时存储的动态开辟的内存空间
对于下面的代码中,有一个11个字符(不包括\0
)的字符串
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
此时hello world\0
存储的位置在_buf[16]
数组中
如果字符串的长度大于16时,则不会存储到_buf[16]
中,而是存储到ptr
指针指向的内存空间
可以推测出,在设计string
类时,底层的成员变量有下面几种
C++ | |
---|---|
1 2 3 4 5 6 7 8 |
|
所以在VS下,第一次和第二次之间是两倍的关系并不是扩容两倍,而是改变了存储位置
reserve()
函数¶
使用reserve()
函数可以为字符串预留指定大小的空间,此时当指定大小远大于前面扩容的大小时一般不会再进行扩容
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
Note
在VS下,使用reserve()
函数指定的大小一般会被编译器扩大一小部分,但是在GCC下指定多少就是多少,所以在上面的代码中,虽然指定的大小为100,但是实际的大小为111 但是不论时哪种编译平台,都要至少保证开辟的大小不能小于指定大小
使用reserve()
函数时,如果已经有空间时,对原始空间进行扩容时不会改变有效字符长度size
值,只会改变capacity
的值,从而达到扩容的效果
Note
注意,若扩容的值小于原始空间时,那么此时reserve()
函数不起任何效果
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
resize()
函数¶
不同于reserve()
函数,使用resize()
函数可以将原始空间扩容并且初始化扩容的空间,默认初始化字符为\0
,当指定为某一个字符后,则将初始化对应字符
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
在上面的代码中,使用resize()
函数时会同时改变size
的大小和capacity
的大小,size
的大小刚好为resize()
函数的参数值,并且默认将其余部分初始化为\0
也可以指定某一个字符
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
Note
使用resize()
函数还可以达到删除字符的效果,当扩容值参数的大小小于已经存在的字符串的长度时
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
Note
注意,尽管使用resize()
函数后改变了size
的大小,但是对于capacity
来说,一旦在开始确定好了大小,那么使用resize()
改变size
的值使其小于已经设定的值,此时不会改变capacity
的大小,因为缩容是非法的,如果支持缩容,那么证明可以支持free
释放部分空间
string类对象的操作¶
此处展示部分可能用得到的成员函数,全部成员函数参考文档:string - C++ Reference (cplusplus.com)
函数 | 功能 | 函数原型 |
---|---|---|
push_back | 在字符串后尾插指定字符 | void push_back (char c); |
append | 在字符串后追加一个字符串 | string& append (const char* s); (常用) |
operator+= | 在字符串后追加字符串或字符 | string& operator+= (const string& str); (追加string类对象) |
string& operator+= (const char* s); (追加字符串) | ||
string& operator+= (char c); (追加字符) |
push_back()
函数¶
使用push_back()
函数可以在字符串后追加字符
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
append()
函数¶
使用append()
函数可以在字符串后追加字符串
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 |
|
operator+=()
函数(+=
运算符重载函数)¶
使用operator+=()
函数可以达到append()
和push_back()
的效果
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
operator+()
函数(+运算符重载函数)¶
使用operator+()
函数可以将两个字符串相加(即合并但不改变原来的字符串)
函数原型 |
---|
string operator+ (const string& lhs, const string& rhs); (将两个string类对象的字符串相加) |
string operator+ (const string& lhs, const char* rhs);``string operator+ (const char* lhs, const string& rhs); (将字符串和对象的字符串相加) |
string operator+ (const string& lhs, char rhs);``string operator+ (char lhs, const string& rhs); (将字符和对象的字符串相加) |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
assign()
函数¶
使用assign()
函数可以将一个对象或者字符串赋值给另一个对象
函数原型 |
---|
string& assign (const string& str); (对象赋值给调用对象) |
string& assign (const string& str, size_t subpos, size_t sublen = npos); (赋值对象中的部分字符给调用对象) |
string& assign (const char* s); (将字符串赋值给调用对象) |
string& assign (const char* s, size_t n); (将部分字符串赋值给调用对象) |
string& assign (size_t n, char c); (使用字符c 填充调用对象的空间) |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
|
insert()
函数¶
使用insert()
函数可以指定插入某个内容到字符串指定位置中
Note
在插入过程中会涉及挪动数据以及扩容问题,所以不建议大量使用
函数原型 |
---|
string& insert (size_t pos, const string& str); (在调用对象的字符串pos 位置中插入对象中的字符串) |
string& insert (size_t pos, const string& str, size_t subpos, size_t sublen = npos); (在调用对象的pos 位置插入对象中subpos 位置开始的指定个数的字符串) |
string& insert (size_t pos, const char* s); (在调用对象pos 位置插入字符串s ) |
string& insert (size_t pos, const char* s, size_t n); (在调用对象pos 位置插入指定个数个字符串中的字符) |
string& insert (size_t pos, size_t n, char c); (在调用对象pos 位置插入n 个字符c )void insert (iterator p, size_t n, char c); (迭代器p 位置开始插入n 个字符c ) |
iterator insert (iterator p, char c); (在调用对象迭代器p 指向位置插入字符c ) |
Note
注意插入字符串时不会覆盖原来pos
位置存在的字符,原来pos
位置及以后的字符向后移动
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
|
erase()
函数¶
使用erase()
函数可以删除指定对象中的内容
函数原型 |
---|
string& erase (size_t pos = 0, size_t len = npos); (删除调用对象pos 位置开始len 长度的字符) |
iterator erase (iterator p); (删除迭代器p 指向位置的字符) |
Note
因为删除字符会涉及到挪动数据,所以不推荐大量使用erase()
函数
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
replace()
函数¶
使用replace()
函数可以替换调用对象的字符串中的字符
Note
因为替换的字符串可能比被替换的字符串长,所以可能涉及到空间的扩容和数据的移动,不推荐大量使用replace()
函数
函数功能 |
---|
string& replace (size_t pos, size_t len, const string& str); (使用对象中的字符串替换调用对象pos 位置开始len 长度的字符串) |
string& replace (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen); (使用对象中的subpos 位置开始的sublen 长度的字符串替换调用对象pos 位置开始的len 长度的字符串) |
string& replace (size_t pos, size_t len, const char* s); (使用字符串s 替换调用对象pos 位置开始的len 长度的字符串) |
string& replace (size_t pos, size_t len, const char* s, size_t n); (使用字符串中的n 个字符替换调用对象pos 位置开始的len 长度的字符串) |
string& replace (size_t pos, size_t len, size_t n, char c); (使用n 个字符替换调用对象pos 位置开始的len 长度的字符串) |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
|
find()
函数¶
使用fine()
函数可以在string对象中从前往后找某一个字符或者字符串
函数原型 |
---|
size_t find (const string& str, size_t pos = 0) const; (在调用对象的字符串中从pos 位置开始找出现对象字符串的开始位置) |
size_t find (const char* s, size_t pos = 0) const; (在调用对象的字符串中从pos 位置找出出现字符串的开始位置) |
size_t find (const char* s, size_t pos, size_t n) const; (在调用对象的字符串中从pos 位置开始找字符串s 中的n 个字符的开始位置) |
size_t find (char c, size_t pos = 0) const; (在调用对象的字符串中从pos 位置开始找字符c 的开始位置) |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
|
针对第三个题目做出的一点优化(包含之前的接口函数的使用)
第一种优化:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
|
第二种优化思路:以空间换时间
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
|
swap()
函数¶
使用swap()
函数可以交换调用对象的字符串和另一个对象中的字符串
Note
对于任意类型,标准库中还有个全局函数swap()
,对比于string类中的swap()
来说,类string中的swap()
函数执行效率会被全局函数swap()
效率更高,因为全局的swap()
函数在拷贝过程中会调用对应对象类的拷贝构造函数,此时会有额外的空间和时间消耗
全局函数swap()
定义:
在前面推测过字符串存储的位置可能是数组或者指针,但是不论是那种,实际上都是地址,只要改变指向两个字符串的指针的指向即可完成交换,所以效率会比全局函数的swap()
高
函数 | 函数原型 |
---|---|
swap() | void swap (string& str); |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
c_str()
函数¶
使用c_str()
函数可以按照C语言字符串的形式返回调用对象中的字符串
函数 | 函数原型 |
---|---|
c_str() | const char* c_str() const; |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
使用场景:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
需要注意,c_str()
函数返回的是一个字符串数组的地址,该数组中的内容和调用对象中的字符串内容相同,但是不能确定后续该字符串数组一直有效,可能调用对象改变会影响字符串数组(甚至在函数调用时不可以返回c_str()
),所以为了使用安全,最好将c_str()
重新拷贝到一个新数组中
substr()
函数¶
使用substr()
函数可以截取字符串中的某一部分字符串作为子字符串返回
函数 | 函数原型 |
---|---|
subStr() | string substr (size_t pos = 0, size_t len = npos) const; |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
|
rfind()
函数¶
使用rfinde()
函数可以从字符串的最后一个字符向前找指定字符或字符串
函数原型(与find() 类似) |
---|
size_t rfind (const string& str, size_t pos = npos) const; |
size_t rfind (const char* s, size_t pos = npos) const; |
size_t rfind (const char* s, size_t pos, size_t n) const; |
size_t rfind (char c, size_t pos = npos) const; |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
find_first_of()
函数¶
使用find_first_of()
函数可以在对象字符串中匹配指定字符串中的内容
函数原型 |
---|
size_t find_first_of (const string& str, size_t pos = 0) const; (从pos 位置开始在调用对象的字符串中匹配对象的字符串中的字符) |
size_t find_first_of (const char* s, size_t pos = 0) const; (从pos 位置开始在调用对象的字符串中匹配字符串中的字符) |
size_t find_first_of (const char* s, size_t pos, size_t n) const; (从pos 位置开始,在调用对象的字符串中匹配字符串中n 位置之前的字符串的字符) |
size_t find_first_of (char c, size_t pos = 0) const; (从pos 位置开始,在调用对象的字符串中匹配字符c ) |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
|
同样的函数还有:
find_last_of()
函数:在字符串中匹配指定字符串的字符最后一次在原始字符串中的位置find_first_not_of()
函数:在字符串中找出指定字符串中不存在的字符第一次出现的位置find_last_not_of()
函数:在字符串中找出指定字符串中不存在的字符最后一次在原始字符串中的位置
relational operators系列函数¶
比较字符串之间关系的运算符:(底层调用compare()
函数)
函数 | 函数原型 |
---|---|
operator==() | bool operator== (const string& lhs, const string& rhs); |
bool operator== (const char* lhs, const string& rhs); | |
bool operator== (const string& lhs, const char* rhs); (判断两个字符串/对象的字符串是否相等) | |
operator!=() | bool operator!= (const string& lhs, const string& rhs); |
bool operator!= (const char* lhs, const string& rhs); | |
bool operator!= (const string& lhs, const char* rhs); (判断两个字符串/对象的字符串是否不相等) | |
operator<() | bool operator< (const string& lhs, const string& rhs); |
bool operator< (const char* lhs, const string& rhs); | |
bool operator< (const string& lhs, const char* rhs); (判断第一个字符串/对象的字符串是否小于第二个字符串/对象的字符串) | |
operator<=() | bool operator<= (const string& lhs, const string& rhs); |
bool operator<= (const char* lhs, const string& rhs); | |
bool operator<= (const string& lhs, const char* rhs); (判断第一个字符串/对象的字符串是否小于等于第二个字符串/对象的字符串) | |
operator>() | bool operator> (const string& lhs, const string& rhs); |
bool operator> (const char* lhs, const string& rhs); | |
bool operator> (const string& lhs, const char* rhs); (判断第一个字符串/对象的字符串是否大于第二个字符串/对象的字符串) | |
operator>=() | bool operator>= (const string& lhs, const string& rhs); |
bool operator>= (const char* lhs, const string& rhs); | |
bool operator>= (const string& lhs, const char* rhs); (判断第一个字符串/对象的字符串是否大于等于第二个字符串/对象的字符串) |
getline()
函数¶
使用getline()
函数可以获取到指定字符(默认'\n'
)结尾之前的字符串,具体内容见C++ IO流部分
Note
不同于cin
,cin
遇到空白字符时就会停止读入,getline()
函数遇到'\n'
(或者指定字符)才结束
函数原型 |
---|
istream& getline (istream& is, string& str, char delim); (获取以字符delim 结尾之前的字符串放入对象str 中) |
istream& getline (istream& is, string& str); (获取以字符'\n' 结尾之前的字符串放入对象str中) |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
Note
使用getline()
函数需要包头文件string
getline()
函数的使用练习:字符串最后一个单词的长度_牛客题霸_牛客网 (nowcoder.com)
参考代码:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
|
string类对象的访问及遍历操作¶
函数 | 功能 |
---|---|
operator[]() | 返回pos 位置的字符 |
begin +end | begin 获取第一个字符的迭代器 + end 获取最后一个字符下一个位置的迭代器 |
范围for | C++11支持更简洁的范围for 的新遍历方式 |
at() | 访问字符串中指定位置的字符 |
Note
注意迭代器中的end
为最后一个字符的下一个位置,一般指向\0
,形成左闭右开区间
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
|
在上面的代码中是,使用了三种遍历字符串的方式,但是实际上常用的方式为下标访问的方式,并且范围for
的本质也是迭代器,auto ptr
本质就是调用s.begin()
函数给string : iterator ptr
,s的本质即为s.end()
,通过汇编代码可以验证这一点
直接使用迭代器:
范围for
:
operator[]()
与at()
函数¶
对于string类来说,可以使用下标进行访问
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
operator[]
和at()
函数均可以使用下标的形式访问字符串,但是at()
函数可以在对字符串进行越界访问时抛出异常,而不是像operator[]
越界访问一样断言终止程序
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 |
|
operator[]
越界访问断言报错:
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
string类迭代器遍历¶
正向遍历¶
- 使用
begin
和end
可以从前往后遍历字符串,使用迭代器iterator
函数 | 函数原型 |
---|---|
begin() | iterator begin(); (针对于普通对象) |
const_iterator begin() const; (针对于const 对象) | |
end() | iterator end(); (针对于普通对象) |
const_iterator end() const; (针对于const 对象) |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
在上面的代码中,因为begin()
和end()
均返回iterator
,所以迭代器类型需要选择iterator
对于const
对象来说,需要使用const
类型的迭代器
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
在上面的代码中,使用了const
类型的迭代器,但是注意该迭代器对于指针来说只是修饰指针指向的内容不可以修改,但是指针可以改变指向
Note
对于const
修饰的迭代器来说,还可以使用cbegin()
和cend()
逆向遍历¶
- 使用
rbegin
和rend
可以从后往前遍历字符串,此时使用的迭代器为reverse_iterator
函数 | 函数原型 |
---|---|
rbegin() | reverse_iterator rbegin(); (针对普通对象) |
const_reverse_iterator rbegin() const; (针对const 对象) | |
rend() | reverse_iterator rend(); (针对普通对象) |
const_reverse_iterator rend() const; (针对const 对象) |
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
|
在上面的代码中,使用rbegin()
和rend()
,返回类型为reverse iterator
,故迭代器类型需要选择reverse_iterator
Note
注意此时ptr1
并不是--
,而是++
,因为此时的rbegin
为字符串最后一个有效字符的前一个位置,而rend
为字符串第一个有效字符的前一个位置,形成左闭右开
当使用迭代器的对象为const
修饰时,迭代器需要同样使用const
修饰的迭代器
C++ | |
---|---|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
在上面的代码中,使用了const
类型的迭代器,但是注意该迭代器对于指针来说只是修饰指针指向的内容不可以修改,但是指针可以改变指向
Note
对于const
修饰的迭代器来说,还可以使用crbegin()
和crend()