1.概述
顺序容器类型 | 描述 | 优点 | 缺点 |
vector | 可变长数组 | 支持快速随机访问 | 在尾部之外的地方插入删除元素麻烦 |
deque | 双向队列 | 支持快速随机访问 | 在首尾部之外的地方插入删除元素麻烦 |
list | 双向链表 | 任何位置插入删除元素快 | 只能双向顺序访问 |
forward_list | 单向链表 | 任何位置插入删除元素快 | 只能单向顺序访问 |
array | 固定长度数组 | 支持快速随机访问 | 不能添加删除元素 |
string | 字符串 | 支持快速随机访问 | 在尾部之外的地方插入删除元素麻烦 |
array定义时需用constexpr常量表达式声明大小。
2.类型别名
3.构造与初始化
C c; //默认初始化为空容器
C c (c2); //拷贝构造初始化容器,c和c2必须相同类型
C c (b, e); //迭代器指定范围初始化容器,array不适用
C c {a, b, c, ...}; //初始化列表初始化容器
C c = {a, b, c, ...};//初始化列表初始化容器
C c (n) //初始化为n个元素,每个元素执行值初始化,string不适用
C c (n, t) //初始化为n个值为t的容器
只有顺序容器(不包含array)的构造函数才能接受大小参数。
区别于内置数组,array支持拷贝操作,前提是两者大小和元素类型都相同。
4.赋值和swap
c1 = c2
c = {a, b, c, ...}
swap(c1, c2) //c1和c2必须具有相同的类型
c1.swap(c2)
//只有顺序容器(不包含array)才可以使用assign
seq.assign(b, e) //将容器内的元素替换为迭代器范围内的值
seq.assign(n, t)
seq.assign({a, b, c, ...})
swap通常比拷贝速度快得多。赋值相关操作会使迭代器和指针失效,但swap操作将容器内容交换并保持迭代器和指针不失效,即指向的元素不变,但已经属于不同的容器。
特殊的,对一个string 掉用swap会导致迭代器和指针失效。
与其它容器不同,swap两个array会真正交换它们的元素。指针和迭代器所绑定的元素保持不变,但元素值已经与另一个array中对应的元素的值进行了交换。
尽量使用非成员函数版的swap
例子
vector v1(10, 1);
vector v2(5, 2);
auto it_v1 = v1.begin();
auto it_v2 = v2.begin();
for (auto &c : v1) cout << c << " ";
cout << endl << *it_v1 << endl;
for (auto &c : v2) cout << c << " ";
cout << endl << *it_v2 << endl;
swap(v1, v2);
for (auto &c : v1) cout << c << " ";
cout << endl << *it_v1 << endl;
for (auto &c : v2) cout << c << " ";
cout << endl << *it_v2 << endl;
array a1 = {1,1,1,1,1};
array a2 = {2,2,2,2,2};
auto it_a1 = a1.begin();
auto it_a2 = a2.begin();
for (auto &c : a1) cout << c << " ";
cout << endl << *it_a1 << endl;
for (auto &c : a2) cout << c << " ";
cout << endl << *it_a2 << endl;
swap(a1, a2);
for (auto &c : a1) cout << c << " ";
cout << endl << *it_a1 << endl;
for (auto &c : a2) cout << c << " ";
cout << endl << *it_a2 << endl;
5.容器大小的操作
forward_list支持max_size和empty,但不支持size。其它每个容器都有三个有关大小的操作。
添加元素
添加元素操作 | 描述 | vector | list | forward_list | array | deque |
push_back emplace_back |
尾部添加元素 | ok | ok | 不支持 | 不支持 | ok |
push_front emplace_front |
首部添加元素 | 不支持 | ok | OK | 不支持 | ok |
insert(p, t) insert(p, n, t) insert(p, b, e) insert(p, {...}) |
在指定p位 置插入元素 |
ok | ok | 有自己 专用版本 |
不支持 | ok |
emplace | 插入元素 | ok | ok | 有自己 专用版本 |
不支持 | ok |
v.push_back("sometring");
v.emplace_back(10,'c');
for (auto &c : v) cout<< c << endl;
c.front()
c.back()
c[n]
c.at(n)
7.删除元素
c.pop_back()
c.pop_front()
c.erase(p)
c.erase(b,e)
c.clear()
8.改变容器的大小
void display(int i){cout << i << " ";}
int main(){
list lst(10, 42);
for_each(lst.begin(), lst.end(), display);
cout << endl;
lst.resize(15);//添加5个元素,执行值初始化
for_each(lst.begin(), lst.end(), display);
cout << endl;
lst.resize(25, -1);//添加10个-1
for_each(lst.begin(), lst.end(), display);
cout << endl;
lst.resize(5);//将容器尺寸改变为5,删除后20个元素
for_each(lst.begin(), lst.end(), display);
cout << endl;
return 0;
}
单向链表有着特殊版本的插入和删除操作,原因在于单向链表自己的特性,只能对后驱元素操作,不能操作元素的前驱。
int main(){
//只能在之后插入或删除
forward_list lst;
//向迭代器之后插入元素,返回指向插入最后的元素的迭代器
auto it1 = lst.insert_after(lst.before_begin(), 2, 2);
cout << *it1 << endl;
auto it2 = lst.insert_after(lst.before_begin(), {1, 3, 9});
cout << *it2 << endl;
for (auto& c : lst) cout << c << " ";
cout << endl;
//删除迭代器之后的元素,返回指向删除元素下一位置的迭代器
auto it3 = lst.erase_after(lst.before_begin());
cout << *it3 << endl;
for (auto& c : lst) cout << c << " ";
cout << endl;
return 0;
}
默认情况下,stack和queue是基于deque实现的,priority_queue是在vector之上实现的。
允许创建一个适配器时,将一个命名的顺序容器作为第二个类型参数,来重载默认容器类型。stack
push_back
pop_back
和back
操作,所以可以用除array和forward_list外任何容器类型构造。