9.1 顺序容器概述
通常使用vector是最好的选择,除非你有更好的理由选择其他容器。
选额容器的基本原则:
- 没有特殊理由就使用vector
- 空间的额外开销很重要,则不要用list和forward_list
- 随机访问:vector、deque
- 任意位置插入或这删除:list和forward_list
- 头尾插入、中间没有操作:deque
- 如果程序只有在读取输入时才需要在容器中间插入元素,随后需要随机访问元素
(1)向vector追加元素,再sort
(2)输入阶段使用list,一旦输入完成,拷贝到vector
容器操作
9.2.3 begin和end成员
9.2.4容器定义和初始化
使用swap
统一使用非成员版本的swap是一个好消息
- 除了array之外,swap不对任何元素进行拷贝、删除或者删除操作,保证在常数时间内完成
- 对一个string的调用swap会导致迭代器失效,其他不会失效
- swap两个array会真正交换他们的元素
9.3.1 向顺序容器添加元素
使用emplace操作
访问成员函数返回的是引用
下标操作和安全的随机访问
运用下标会发生越界情况,编译器不会检查。所以可以使用at成员函数,如果越界会抛出一个out_of_range的异常。
9.3.3 删除元素
9.3.5 改变容器的大小
9.3.6 容器操作可能使迭代器失效
向容器中添加元素和从容器中删除元素操作都有可能会使指向容器元素的指针、引用或迭代器失效。
添加元素
1.vector或是string
如果存储空间被重新分配,则所有迭代器、指针和引用都都会失效。
如果未重新分配,那么添加位置之后的所有迭代器、指针和引用都失效
2.deque
插入任何位置迭代器都会失效
插入除了首位的任何位置,指针和引用也会失效
3.list和forward_list
都有效
建议:最小化要求迭代器必须保持有效地程序片段
保证每次该百年容器的操作之后都正确地重新定位迭代器
编写改变容器地循环程序
不要保存end返回的迭代器
每次都调用.end()成员函数来获得尾指针,防止失效。
9.4vector对象是如何增长的
管理容量的成员函数
调用reserve永远也不会减少容器占用的内存空间
调用shrink_to_fit只是一个请求,标准库并不保证退还内存
vector每次扩容将当前容量翻倍
9.5 额外的string操作
9.5.1 构造string的其他方法
从一个const char*创建string的时候,指针指向的数组必须以空字符结尾,拷贝操作遇到空字符时停止。如果我们还传递给构造函数一个计数值并且小于等于数组大小,那么可以不以空字符结尾。
substr操作
9.5.2改变string的其他方法
append和replace函数
9.5.3搜索操作
区分大小写
string s("hello world");
auto pos1=s.find("hello");//pos1=0
string name("a1b2c3"),numbers("123456789");
auto pos2=name.find_first_of(numbers);
auto pos3=name.find_first_not_of(numbers);
compare函数
等于、大于或者小于
返回0、正数或者负数
9.5.5 数值转换
int s=1;
string s=to_string(s);
double d=stod(s);
string s1("pi=3.1415");
double pi=stod(s1.substr(s1.find_first_of("+-.1234567890")));//3.14
9.6 容器适配器
适配器是标准库中的一个通用概念,需要容器具有添加和删除元素的能力(array和forward_list不行)
定义一个适配器
栈适配器
队列适配器