Cpp STL: std::string
string类
ctors
1 | // 定义:uint指size_type,即size_t,或许是unsigned int或unsigned long long |
与C风格字符串不同,string不带'\0',在输入时也不需要考虑字符串的长度,string类会自动调整到刚刚好的空间,它所能容纳的长度为string::npos=-1(无符号整型的最大值),在不同位数处理器下会有不同,可能是unsigned long long或unsigned int的最大值
这些构造函数使得需要创建子串对象时只需要知道起始点和子串字符数,就能很快算出参数
关于复制构造函数和移动构造函数的区别,以一个临时对象为例,假设还需要使用这个对象的内容,在被析构时,如果使用复制构造函数转移内容,需要:
- 申请新的堆内存
- 复制粘贴临时对象的内容
- 释放临时对象的堆内存
而移动构造函数只需要将临时对象的堆内存转移给新对象,这个ctor通常由编译器自行选择使用,以优化性能,如果手动使用,需要注意它不保证const,可能造成问题
方法
重载运算符
关于部分重载运算符如=,+=,==,[],<<,>>等,较容易理解,不赘述
关于比较运算符>,<,>=,<=,它们调用的方法类似C中的strcmp(),是比较字符的ASCII码大小而非长度
string类没有定义-=,-(),-(other)运算符
需要注意用[]访问时,编译时不会抛出异常,即越界时有可能发生运行时错误
遍历访问与转换
使用[]时,完全靠自己谨慎来保证不出错,而string类提供at(int)方法,在越界时,会抛出out_of_range异常,这意味着可以try_catch处理它而非立刻终止程序(这里的越界指的是提供的参数大于等于size(),因为string尾部不含'\0')
关于length()和size()方法,它们功能一样,都返回总字符数,size()的出现是为了配合STL容器要求的统一名称
所有STL都提供便于遍历的类似指针的迭代器,通常用以下方法获取string迭代器:
begin():返回指向开头字符的正向迭代器end():返回指向结尾字符的下一个位置的正向迭代器rbegin():返回指向结尾字符的反向迭代器(reserve begin())rend():返回指向开头字符的上一个位置的反向迭代器
在这些方法前加上'c'(例如cbegin()),将返回只读迭代器,用于处理const修饰的对象,但事实上,这四个方法都有对应的重载版本,当该对象被const修饰时,自动使用这个版本返回只读迭代器,所以这个'c'可加可不加
那么遍历变得很简单,而不需要用[]或at()访问字符:
1 | for (auto it = str.begin();it != str.end();it++){ |
在std中,transform()方法能够快速遍历STL容器并应用所提供的函数或函数指针:
1 | // 定义:InIt指InputIterator,OutIt指OutputIterator |
增删改查
insert():用于前插入1
2
3
4
5
6
7
8// 定义
insert(uint idx,string&); // 将提供的string插到str[idx]前
insert(uint idx,const char*);// 提供C风格字符串,会删除\0
// 提供string引用,将它从下标idx_2开始数n个字符的子串插到str[idx_1]前
// (经测试,虽然没有char*的函数重载,但传入char*是可行的)
insert(uint idx_1,string&,uint idx_2,uint n);
// 相当于上一条中,idx_2=0
insert(uint idx,const char*,uint n);// 提供string&是不行的append():用于后插入,完全可以被operator+()和insert()替代erase():删除某字符,自动调整空间