【与C++的邂逅】--- string容器使用
Welcome to 9ilk's Code World

(๑•́ ₃ •̀๑) 个人主页: 9ilk
(๑•́ ₃ •̀๑) 文章专栏: 与C++的邂逅
本篇博客我们将来了解string容器本身以及接口的使用。

string是串,本质是一个字符数组,可以对其进行增删查改。
🏠 string构造
//常用 string s1; string s2("hello world"); string s3(s2); //不常用 string s4(s2,3,5); // string (const string& str, size_t pos, size_t len = npos) string s5(s2,3); string s6(s2,3,30); string s7("hello world",5) //string (const char* s, size_t n) string s8(10,'x'); //string (size_t n, char c);对于string的构造,我们常用的是它的无参构造,拷贝构造等。注意:在库中pos通常代表位置,n代表的是个数。
- npos
由库中文档说明,我们可以知道 :
1. npos是string里的一个const静态成员变量,类型是size_t,缺省值给的是-1(整形最大).
2. 当使用substring的这个构造时,从str的pos位置开始拷贝构造,如果要构造的长度len大于后面的长度,则有多少拷贝多少直到拷贝到结尾 .
3. 缺省参数npos是整形最大值,一定大于后面的长度,不传第三个参数默认拷贝到结尾.
string s2("hello world"); // string (const string& str, size_t pos, size_t len = npos) string s4(s2,3,5); //拷贝5个字符 string s5(s2,3); //拷贝到结尾 string s6(s2,3,30);//拷贝到结尾- 隐式类型转换在构造中的应用
string s1("hello world"); //隐式类型转换 string s2 = "hello world"; const string& s3 = "hello world"; //以及后面其他接口也可以使用... push_back("hello world");说明 :
1. 对于s2是先调用常量字符串的构造生成一个临时对象,再调用拷贝构造将临时对象拷贝给s2.
2. 对于s3,它引用的是临时对象,而临时对象具有"常性",因此需要是const引用.
🏠 元素访问方式
📌 operator[ ]
char& operator[] (size_t pos); const char& operator[] (size_t pos) const;- 引用返回
int main() { string s = "hello"; for (size_t i = 0; i < s.size(); i++) { cout << s.operator[](i) << " "; //显式[]+下标访问对象元素 cout << s[i] << " ";//隐式[]+下标访问对象元素 } for (size_t i = 0; i < s.size(); i++) { s[i]++; //修改访问元素内容 } return 0; }由于string类重载了[ ]运算符,所以我们可以直接利用[ ] + 下标访问对象中的元素;同时由于是引用返回,所以我们可以通过[ ] + 下标修改对应位置的元素内容,也就是可读可写.
class string { /... private: char* _str; size_t _size; int _capacity; } char& operator[](size_t pos) { assert(i < _size); return _str[i]; }string类一般是动态开辟内存来储存字符元素,所以实现operator[ ]一般返回的是在堆上的空间,因此我们不用担心传引用返回时返回的是一个局部对象.
传引用返回优势 :
1. 能修改返回对象.
2. 减少拷贝.
- string类重载的[]运算符还会执行严格的越界检查,只要下标超过size或小于0就报错.
- opertaor[ ]有两个版本,一个是非const,返回对象可修改,是典型的可读可写;另一个是const版本,返回对象内容不可修改.
const string s2("hello"); s2[0] = 'x'; //不可修改 调用const版本的operator[] string s1("hello"); s1[0] = 'x';//调用非const版本的opeator[] 1. const版本重载的[ ]主要是给const对象用的,毕竟const对象无法调用非const版本,这是权限的扩大.
2. 对于const和非const对象其实都能调用const版本的重载,但却重载出两个版本,这是因为各自有不同的需求(比如只有一个const版本的operator[ ],对于普通string对象就不能修改了,不符合我们的要求,如果重载了两个版本则调用更匹配的,普通对象调用普通版本,const对象调用const版本).
3.具体实践中重载[]操作符看具体需求.
📌 迭代器
迭代器目前我们可以理解为具有和指针类似行为的东西,但实际上不一定是指针.
string::iterator it = s.begin(); while (it != s.end()) { cout << *it << endl; //类似指针解引用 ++it;//类似指针++ } auto it = s.begin();迭代器访问元素是所有容器(除stack,queue外)通用的访问方式,他们通用的将迭代器命名为iterator,头元素位置的迭代器和尾元素位置的迭代器都命名为begin和end,它们都是定义在类域里的成员函数.
注 : C++11之后,直接使用auto定义迭代器,让编译器推到迭代器的类型.
for (auto ch : s) cout << ch << endl;C++11之后我们更喜欢用范围for来访问string类元素,它底层也是利用的迭代器.
- begin与end

对于begin返回的是开始位置,对于end返回的是最后一个字符的下一个位置,在string类中大概就是\0的位置.
- 迭代器的版本
const string s1("hello"); string::const_iterator it1 = s1.begin(); while (it1 != s1.end()) { cout << *it1 << endl;//无法修改 } 迭代器分为iterator(可读可写)和const_iterator(只读),对于const对象匹配的是返回const_iterator的begin().下面我们来区分const iterator , iterator 和 const_iterator.