1. 顺序容器类型
顺序容器 | |
vector | 支持快速随机访问 |
list | 支持快速插入、删除 |
deque | 双端队列 |
顺序容器适配器 | |
stack | 后进先出(LIFO)栈 |
queue | 先进后出(FIFO)栈 |
priority_queue | 有优先级管理的队列 |
2. 容器元素的初始化
C<T> c | 创建空容器 |
C c(c2) | 创建容器c2的副本:容器类型和元素类型必须相同 |
C c(b, e) | c是迭代器b和e标志范围的副本 : 容器类型可以不一样,容器的元素需要能相互兼容 所以,可以使用内置数组的一对指针来初始化容器。 |
C c(n, t ) | 用n个值为 t 的元素创建容器:只适用于顺序容器 |
C c(n) | 创建有n个元素的容器 |
3. 容器内元素的类型约束
元素类型必须支持赋值运算:引用不能做容器内的元素
元素类型的对象必须可以复制:输入输出(IO)标准库类型不能复制或赋值,不能作为容器的元素
4. 容器的容器
必须用空格隔开两个相邻的 > 符号,否则,系统会认为>>是单个右移操作符。
vector<vector<string> > lines;
5. 迭代器运算和支持的操作
iter1 == iter2 iter2 != iter2 | 指向同一容器中同一元素,或指向同一容器超出末端的下一元素时,两个迭代器相等。 |
下面这些只适用vector和deque, 不适用 list | list 不支持算术运算,也不支持关系运算,只提供 自增、自检、相等、不等 运算。 |
iter + n iter - n | 将指向容器中前面(后面)第n个元素的迭代器,结果必须是容器中元素或end |
iter1 += iter2 iter1 -= iter2 | ??? |
iter1 - iter2 | 两个必须指向同一容器 |
>, >=, <, <= | 只适用于指向同一容器的迭代器,按照在容器中的顺序比较 |
6. 容器定义的类型别名
size_type | 无符号整型,容器长度 |
value_type | 元素类型 |
difference_type | 两迭代器的差值,可为负数 |
reference | 元素左值类型,是value_type&的同义词 |
7. c.rbegin(); c.rend(); 返回逆序迭代器。
8. 顺序容器添加元素
c.push_back(t) | 尾部添加值为t的元素. 返回void |
c.push_front(t) | 前端添加值为t的元素。返回void 只适用 list 和 deque 容器类型,不适用vector |
c.insert(p, t) | 在迭代器P前面插入t, 返回指向新添加元素的迭代器 |
c.insert(p, n, t) | 在P前面插入n个t , 返回void |
c.insert(p, b, e) | 在p前面插入迭代器b,e范围内的元素,返回void |
9. 任何 insert 或 push 操作都可能导致迭代器失效。
当编写循环将元素插入到vector或deque容器中时,程序必须确保迭代器在每次循环后都得到更新。
不要存储end操作符返回的迭代器,添加或删除deque 或 vector 容器内元素都会导致存储的迭代器失效。
10. 顺序容器的大小操作
c.size() | 返回容器c中的元素个数, 返回类型 c::size_type |
c.max_size() | 返回容器c可容纳的最多元素个数 |
c.empty() | 标记容器大小是否为0 |
e.resize(n) | 调整容器c的长度大小,使其能容纳N个元素 若 n < c.size(), 则删除多余的元素;否则,添加采用值初始化的新元素 resize 若压缩了容器,指向已删除元素的迭代器失效。 |
c.resize(n, t ) | 调整容器长度,新添加的元素值都为 t |
11. 访问顺序容器内元素
c.back() | 引用 , list<int>::reference val = ilist.back(); list<int>::reference val = *--ilist.end(); |
c.front() | 引用 |
c[n] | 返回下标为n的元素。 只适用vector和deque, 不适用 list |
c.at(n) | 返回下标为n的元素。 只适用vector和deque, 不适用 list |
12. 删除顺序容器内操作
删除操作要特别注意迭代器失效的情况,需要重新获取迭代器的值,之前的保存的值不能使用。
c.erase(p) | 删除容器内P指向的元素 返回一个迭代器,指向被删元素后面的元素; 若p为最后一个元素,则返回end(); 若p为end(), 则该函数未定义。 |
c.erase(b, e) | 删除 b, e 所标记范围内所有元素。返回值参考上面的erase |
c.clear() | 删除容器内所有元素, 返回void |
c.pop_back() | 删除最后一个元素,返回void |
c.pop_front() | 删除第一个元素,返回void 只适用 list 和 deque 容器类型,不适用vector |
eg, pop_front操作通常与front操作配套使用,实现以栈的方式处理容器。
while(!ilist.empty())
{
process(ilist.front());
ilist.pop_front();
}
//删除特定元素,先用find得到迭代器,再erase删除。
string searchValue("Quasimodo");
list<string>::iterator iter = find(slist.begin(), slist.end(), searchValue);
if(iter != slist.end())
slist.erase(iter);
13. 顺序容器的赋值
c1 = c2 | 删除容器c1的所有元素,让后将c2的元素复制给c1。 两个容器的类型和元素类型必须相同。 |
c1.swap(c2) | 交换内容:c1存放c2原来的元素,c2存放c1原来存放的元素。两者类型必须相同。 该函数执行速度比c2复制给c1要快。 由于容器内没有移动任何元素,故迭代器不会失效 |
c.assign(b, e) | 重新设置c的元素:将b,e范围内元素复制到c中。 b,e必须不是指向c中元素的迭代器. (因为assign首先会删除原来存储的元素) 如果两个容器不同,元素类型相互兼容,不能用'=', 只能用assign |
c.assign(n, t ) | 将容器C重设为存储n个值为 t 的元素。 |
14. vector 容器的自增长
vector容器的元素以连续的方式存放。如果容器没有地方存放新元素,vector需要重新分配内存来存储原来的元素和新添加的元素。这样做性能比较慢。
不连续存储元素的容器,不存在这样的问题。如,list中新加元素,只需将其加到链表中,不需要重新分配内存,也不需要复制任何已存在的元素。
为了使vector容器实现快速的内存分配,其实际分配的容量要比当前所需的空间多一些。vector容器预留了这些额外的存储区,用于存放新添加的元素。
capacity | 获取在容器需要分配更多的存储空间之前能够存储的元素总数。 |
reserve | 告诉vector容器应该预留多少个元素的存储空间。 |
15. 容器的选用
vector和deque容器能快速随机访问,但是在容器任意位置插入或删除元素比在容器尾部插入和删除的开销更大;
list类型在任何位置都能快速插入和删除,但代价是元素的随机访问开销较大。
除非找到选择使用其他容器的更好理由,否则vector容器都是最佳选择。
如果无法确定某种应用应该采用哪种容器,则编写代码时尝试只使用vector和list容器都提供的操作:使用迭代器,而不是下标,并且避免随机访问元素。
这样编写代码,在必要时,可很方便的将程序从使用vector容器修改为使用list容器。
16. 再谈string类型
。。。略
17. 容器适配器
。。。略
<END>