目录
string构造接口(Construct string object)
string的元素访问(读写)
迭代器
string构造接口(Construct string object)
string相比于C语言的字符数组要好用的多,无论是在初始化还是在读写方面都方便许多。
以basic_string<char> 为例,来看一下它的构造接口:
1、 第一个string():无参类型的构造,字符串长度为0。
2、string (const string& str) :拷贝构造
3、string (const string& str, size_t pos, size_t len = npos)
以一个字符串的第pos个字符后一位开始,长度为len构造一个字符串:
如果构造字符串的过程超过了目标字符串最后一位,那么将拷贝到最后一位停止:
4、string (const char* s) :以字符串为参数构造,有两种形式。
5、string (const char* s, size_t n) :从一个字符串的第n+1位开始进行构造:
6、string (size_t n, char c) :构造n个c字符的字符串:
7、string (InputIterator first, InputIterator last) :从first开始到 last结束进行构造字符串:
此外对多个字符串还能进行拼接,使用重载运算符 += 即可:
上面所讲,红色标注的为重点,其他的了解用法即可。
string的元素访问(读写)
string中也对运算符 [ ]进行了重载,使得可以通过下标来访问元素。
[ ] 运算符重载原型如下:
char& operator[](size_t i)
{
assert(i < s0.size() );
return _str[i];
}
并且相比于静态数组,它可以防止溢出。
这里也可以使用范围for:
看起来范围for好像是比用下标访问要简单一点,但是有的情况下用下标访问比较好,比如需要逆置上面的数组时:
迭代器
上面的数组还有第三种表示方式,就是迭代器。
迭代器是string类里定义的类型,但不是内部类,只是在其中定义,属于string类。
迭代器 iterators是一种行为像指针的类型,但它底层是不是指针不确定,具体要看实现,但是它的用法很像指针,且看他如何访问数组元素:
string s0("abcd1234");
string::iterator it = s0.begin();
while (it != s0.end())
{
*it += 1;
++it;
}
it = s0.begin();
while (it != s0.end())
{
cout << *it << " ";
++it;
}
cout << endl;
it 是迭代器的对象,迭代器里面都有begin和end,分别表示第一个元素和最后一个的下一个元素。
这是正向迭代器,还有反向迭代器:
string::reverse_iterator rit = s0.rbegin();
while (rit != s0.rend())
{
*rit += 1;
++rit;
}
rit = s0.rbegin();
while (rit != s0.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
与正向相对,反向开始是rbegin,结束是rend,它是倒着遍历的。
看到迭代器的示例,有人会问 “这迭代器看上去非常麻烦,不好理解而且难记,不如直接用下标访问的方式 ”
————下标访问的方式在string和vector(顺序表)中可以使用,但是在其他容器(如map)就无法使用了。而迭代器是一种容器通用的遍历方式,具有普遍性。
迭代器还有const修饰类型的,上面讲的迭代器对数据可读可写,const修饰的是只读属性,像print这种接口就要写成const修饰的。
void print(const string& s)
{
string::const_iterator it = s.begin();
while (it != s.end())
{
cout << *it << " ";
++it;
}
cout << endl;
}
int main()
{
string s0("abcd");
print(s0);
return 0;
}
string::const_iterator it = s.begin(); 这里要用const修饰迭代器对象,防止修改迭代器里的内容(*it)注意:这里不能写成 const string::iterator it = s.begin(); 这种是防止修改 it本身,而我们要遍历是需要修改 it 的,而 it 指向的内容不能修改。
const修饰的迭代器有正向的,也就有反向的。
void Test1()
{
string s0 = "qwer";
string::const_reverse_iterator rit = s0.rbegin();
while (rit != s0.rend())
{
cout << *rit << " ";
++rit;
}
cout << endl;
}
看上去确实长了点,但是有的时候是不可避免的,只要意思表达清楚即可,何况库里面也是这么使用的。
总结:正向、反向迭代器可以读取和修改容器数据,而const正向、反向迭代器可以读取和修改容器数据。
那么什么时候需要const版本,什么时候需要非const版本呢?
1、当数据是只读的,只需要const版本;
2、当数据是只写的,只需要非const版本;
3、当数据是可读可写的,两个都需要。