标准库容器是特定类型对象的集合,类型几乎没有限制,容器一般都定义在同名的头文件中,都是类模板,少部分还要额外元素信息。
容器类型上的操作形成了一种层次:
- 通用操作:适用于所有容器类型。
- 特有操作:每种容器类型特有。
- 顺序容器特有
- 关联容器特有
- 无序容器特有
- 小众操作:适用于小部分容器,如string特有。
类型别名
```cpp iterator //读写迭代器 const_iterator //只读迭代器 size_type //无符号,足够保存容器大小 difference_type //有符号,保存迭代器距离 value_type //元素类型 reference //元素左值类型,等价于value_type&,如int&引用。 const reference //元素const左值类型,例如const int&
list
<a name="xsvST"></a>## 构造函数```cppC c; //默认构造函数,构造空容器C c1(c2); //构造c2的拷贝,也就是c1C c1 = c2; //如果是array还必须大小相同C c(b, e); //构造两个迭代器b、e之间的拷贝,array不支持//容器之间类型可以不同,元素类型也可以不同(能转换)C c{a, b, c...}; //列表初始化,隐含指定了容器大小。C c = {a, b, c...}; //如果是array,数量=容器大小,数量不能超,少了值初始化(默认构造)。//只有顺序容器(除array)构造函数才接受大小参数C seq(n); //n个元素,值初始化,元素类型必须支持默认初始化,explicitC seq(n, t); //n个值为t的元素/********************例子************************/list<string> ls;vector<const char*> vcc;list<string> ls1(ls); //正确,类型和元素类型要匹配deque<string> ds(ls); //错误:容器类型不匹配vector<string> vs(ls); //错误:容器类型不匹配list<const char*> lcc; //错误:元素类型不匹配forward_list<string> fls(vcc.begin(),vcc.end()); //正确,元素可转换。array<int, 10> ial; //10个默认初始化的intarray<int, 10> ia2 = (0,1,2,3,4,5,6,7,8,9); //列表初始化array<int, 10> ia3 = {42}; //ia3[0]为42, 剩余元素为0vector<int> ivec(10 , -1); //10 个 int 元素,每个都初始化为-1list<string> svec(10,"hi!"); //10 个 strings; 每个都初始化为“hi!"forward_list<int> ivec(10); //10 个元素,每个都初始化为 0deque<string> svec(10); //10 个元素,每个都是空stringarray<int, 10>::size_type i; //array必须指定元素类型、数量array<int>::size_type j; //错误:array<int>不是一个类型
赋值
//赋值:元素类型必须相同,会让c1的内部迭代器、指针、引用失效c1 = c2; //赋值替换:c1的元素替换为c2c1 = {a, b, c...}; //赋值替换:c1的元素替换为列表元素,array不适用。//赋值:仅适合顺序容器,元素类型能转换即可。seq.assign(b, e); //范围替换,b、e不能指向seqseq.assign(il); //赋值替换:il是初始化列表seq.assign(n, t); //赋值替换:n个值为t的元素
swap
//交换:不会让a的内部迭代器、引用、指针失效,但是string、array的会失效。//交换只是改变a、b数据结构,并未拷贝,所以比拷贝赋值快得多。//string、array是真正拷贝元素,所以上面的会失效。a.swap(b); //a、b元素交换,类型必须相同,早期是这个成员函数版本。swap(a, b); //同上等价,推荐使用这个。iterator first = a.begin();swap(a, b); //first没有失效,但是first指向了b.begin()
大小
c.size(); //size_type,元素数目,不支持forward_listc.max_size(); //size_type,可保存最大数目c.empty(); //是否空
插入、删除
//array不支持,不同容器,这些接口会不同。c.insert(args) //args拷贝进cc.emplace(inits) //inits构造C中的一个元素c.erase(args) //删除args指定元素c.clear() //清空容器,返回void
关系运算
//容器必须相同,元素必须相同。//实质:元素逐个进行关系运算,所以元素必须支持相应的关系运算,可参考string的关系运算。==, != //容器是否相等、不相等,所有容器都支持< , <=, >, >= //无序、关联容器不支持a == b //true:大小相同 && 元素数量相等a <= b //逐个运算,a的全部元素都<=b元素。vector<int> v1 = {1, 3, 5, 7, 9, 12};vector<int> v2 = {1, 3, 9};vector<int> v3 = {1, 3, 5, 7 };vector<int> v4 = {1, 3, 5, 7, 9, 12};v1 < v2 //true: vl和v2在元素[2]处不同:vl[2]小于等于v2[2]v1 < v3 //false: 所有元素都相等,但v3中元素数目更少v1 == v4 //true: 每个元素都相等,且vl和v4大小相同v1 == v2 //false: v2元素数目比vl少
获取迭代器
迭代器范围(range)是标准库的基础,由 [ begin、end ) 组成,注意是左闭右开区间,并没有包含end。为什么用左闭合,因为:
- begin == end,为空。
- begin != end,迭代结束标记 ```cpp c.begin(), c.end() //首尾迭代器,尾是指向最后一个元素的后面。 c.cbegin(), c.cend() //只读首尾迭代器。
list
<a name="hJoVe"></a>## 反向容器```cpp//forward_list不支持reverse_iterator //按逆序寻址元素的迭代器const_reverse_iterator //上面的const版c.rbegin() //返回指向尾元素的迭代器c.rend() //返回指向首元素前面位置的迭代器c.crbegin(), c.crend() //上面的const版
