C++容器分为两种:1、顺序容器:按元素加入容器的顺序存储;2、关联容器:按关键字的值存储;
所有顺序容器都提供了快速顺序访问的能力,但在1、插入/删除元素的代价,2、非顺序访问元素的代价上有所牺牲。
几种顺序容器:
vector: 可变大小数组。支持快速随机访问,在尾部之外的位置插入/删除元素困难。
deque: 双端队列,支持快速随机访问,在头尾插入删除快。
list: 双向链表,只支持双向顺序访问,在list的任何位置进行插入/删除都很快。
forward_list: 单向链表,只支持单向顺序访问,在链表任何位置插入/删除速度都很快。
array: 固定大小数组,支持快速随机访问,只能修改元素值。
string: 与vector相似的容器,但专门用于保存字符,随机访问快,在尾部插入/删除速度快。
除了array其他容器都提供高效灵活的内存管理。
如何选择容器?
1、除非有很好的理由,否则应选择vector;
2、若元素很小,或不希望有太多额外空间开销,不要选择list或forward_list;
3、若需要在头尾插入或删除元素,且不会在中间插入或删除元素,选择deque;
4、若要支持随机访问,选择deque或vector;
5、若需要在中间插入元素,选择list或forward_list;
6、若只在创建时需要在中间插入元素,且要求在使用时支持随机访问:可以先试试在vector尾部插入元素后,使用sort()将元素排序到中间位置,如果必须在中间插入,先使用list,再将list中的元素拷贝到vector中。
7、若要求既要在中间插入删除元素,又要随机访问,则依据随机访问和中间插入删除的频率综合考虑性能选择。
每个容器都定义在同名头文件中。
只有顺序容器支持的操作(除array):
- 值初始化:
1、C seq(10); // 创建一个名为seq的顺序容器对象,容器对象包含10个元素,每个元素都使用默认初始化;
2、C seq(10, t); // 创建一个名为seq的顺序容器对象,容器对象包含10个元素,每个元素都初始化为值t;
- assign(替换容器内容为指定元素, 仅支持顺序容器):
a赋值运算符要求左边和右边的运算对象具有相同的类型。它将右边运算对象中所有元素拷贝到左边运算对象中。顺序容器(array除外)还定义了一个名为assign的成员,允许我们从一个不同但相容的类型赋值,或者从容器的一个子序列赋值。assign操作用参数所指定的元素(的拷贝)替换左边容器中的所有元素。
seq.assign(b, e); // 用迭代器序列[b, e) 替换顺序容器对象seq,迭代器的容器对象类型与seq不相同,但也是顺序容器。
seq.assign(il); // 用列表il的内容替换顺序容器对象seq中的内容
seq.assign(n, t); // 用n个值为t的元素替换容器对象seq中的元素
- 除无序关联容器外(即顺序容器,有序关联容器)其他容器都支持比较运算符:
比较两个容器:大小相同,元素相等则相等,否则不等;若一个容器A的元素都对应等于容器B的元素,但B还有多余元素,则B>A;否则比较大小的结果取决于第一个不相等元素的大小;
- 顺序容器都支持下标操作:
seq[i]; seq.at(i); // 访问第i+1个元素(下标为i)
- 都支持back()/front() (得到首尾元素值的拷贝)
- 都支持resize:
resize(n); // 调整容器大小为 n个元素,多于n的元素被抛弃;
resize(n, t); // 调整大小为n并将多余元素赋值为t;
对于vector/deque和string,还支持:
reserve不改变原来的容器内容,即若n小于容器现有元素个数,容器大小不变,而当n大于容器现有元素个数时,容器大小依旧不变,只对所在的内存空间重新分配,扩容至至少为n。
- 建议尽量使用reserve而不是resize