9.1 概述
-
容器种类
- vector
- deque 双端队列
- list 双向链表
- forward_list 单项链表
- array 固定大小数组
-
特性
- vector、string顺序存储,插入删除较为耗时,但可以随机访问
- deque支持随机访问,在中间位置插入/删除代价很高,但在两端很快
- array 比内置数组更加安全
-
选择容器的基本原则
- 一般先考虑vector
- 程序又很多小的元素,且空间的额外开销很重要,则不要使用list、forward_list
- 要求随机访问则使用vector或者deque
- 要求在中间插入/删除,使用list、forward_list
- 只在头尾插入删除,而且不会发生在中间,则使用deque
-
反向容器 reverse_iterator 不适用于forward_list
-
类型别名
- const_iterator 只读取元素,不能修改
- size_type 足够保存容器的大小
- value_type 元素类型
- different_type 两个迭代器之间的距离
- reference 元素的左值类型=value_type&
- const_reference
9.2 容器定义和初始化
-
容器的定义和初始化
除array外,其他顺序容器的默认构造函数都会创建一个指定类型的容器,且都可以接收大小和初始值参数
C c(b,e); //用b,e范围内的元素初始化c C c(n,t); //用n个t初始化c
-
将一个容器初始化为另一个容器的拷贝时,两个容器的类型及其元素类型必须匹配,不过当使用迭代器参数来却低估拷贝范围时,可以不要求容器类型相同,同时元素类型也可不相同,只要能进行类型转换即可
list<string> authors={"a","b","c"}; vector<const char*> articles={"the","an","of"}; list<string> list2(authors); //正确,类型匹配 deque<string> authList(authors); //错误,容器类型不匹配 vector<string> words(articles); //错误,类型不匹配 //正确,元素类型可以进行转换 forward_list<string> words(articles.begin(),articles.end());
-
列表初始化时,显式地指定了每个元素地值,除array外,初始化列表还隐含了容器地大小
-
array 其大小也是类型的一部分,定义时,应指定其类型和大小,与内置数组不同,array可以进行拷贝和对象赋值
array<int,10> A={0,1.....,9}; array<int,10> copy=A; //正确
9.3 容器操作
-
赋值与swap
-
赋值
c1=c2; //c1所有元素都会被替换为c2的元素,大小也改变为c2的大小
-
assign
仅适用于顺序容器(除array)外,【赋值运算】要求两边具有相同类型。
assign
允许从一个不相同但相容的类型赋值,或从容器的一个子序列赋值list<string> name; vector<const char*> old_style; name=style; //错误 name.assign(old_style.cbegin(),old_style.cend()); //正确
-
swap
两个容器内容交换,除array外,只交换了内部数据结构,并未交换元素本身,调用swap,除string之外的迭代器都不会失效,swap有两个版本,一般使用非成员版本
swap(c1,c2)
-
-
容器操作
-
insert
//在给定的迭代器之前插入元素 slist.insert(slist.begin(),"hello"); //插入范围内元素 svect.insert(svect.end(),10,"hello"); scevt.insert(svect.end(),b,e); //指定插入内容范围
insert返回 第一个新加入元素的迭代器
-
emplace
直接构造,而不是拷贝元素
emplace 将参数传递给元素类型的构造函数 假设A类型的构造函数,A(int,string); c.emplace_back(10,"hello"); c.push_back(A(10,"hello"));
-
访问元素
- 所有顺序容器都有front成员函数,除array外都有back成员函数,返回首尾元素的引用
- 在容器中访问元素的成员函数返回的都是元素的引用,(front,back,下标,at)
- at 操作会执行是否范围检查,若越界则会报out_of_range异常
- 删除元素,
pop_back()/pop_front()/erase()/clear()
返回删除之后位置上的迭代器
-
-
forward_list
的操作- 没有定义insert,emplace,erase
- 定义了特殊的操作,
insert_after,emplace_after,erase_after
- 还定义了首前迭代器
before_begin()
-
vector对象的增长
通常会分配比新的空间需求更大的内存空间,留作后续使用,减少重新分配内存操作
reserve(n)
分配至少n个元素空间,仅影响预先分配多大的内存空间,不改变容器的元素数量resize()
只改变元素数量,不改变容器的容量
9.4 string的操作
-
substr
参数为可选的开始位置和数量
s.substr(pos,n); //pos默认值为0,n的默认值为s.size()-pos
-
insert和erase
s.insert(s.size(),5,'A'); //末尾加5个A s.erase(s.size(),-5,5); //删除最后5个字符
-
string 搜索
s.find(args); //args在s中出现的第一个位置 s.rfind(args); //最后一次出现的位置 s.find_first_of(args); //s中查找args中任意一个字符第一次出现在s中的位置 s.find_last_of(args); s.find_first_not_of(args); s.find_last_not_of(args); args的构成 c,pos 字符:c 位置:pos s2,pos 串:s2 cp,pos 指向c风格字符串的指针:cp cp,pos,n 从pos位置起,查找cp字符串的前n个字符
-
数值转换
要转换为数值的string 第一个非空白字符必须是数值中可能出现的字符
to_string(val); //val为任意算术类型 stoi(s,p,b); //P:保存s中第一个非数值字符下标,默认为0,b:基数,默认为10 stof(s,p); stod(s,p); stold(s,p);