标准库容器是特定类型对象的集合,类型几乎没有限制,容器一般都定义在同名的头文件中,都是类模板,少部分还要额外元素信息。
容器类型上的操作形成了一种层次:

  • 通用操作:适用于所有容器类型。
  • 特有操作:每种容器类型特有。
    • 顺序容器特有
    • 关联容器特有
    • 无序容器特有
  • 小众操作:适用于小部分容器,如string特有。

    类型别名

    ```cpp iterator //读写迭代器 const_iterator //只读迭代器 size_type //无符号,足够保存容器大小 difference_type //有符号,保存迭代器距离 value_type //元素类型 reference //元素左值类型,等价于value_type&,如int&引用。 const reference //元素const左值类型,例如const int&

list::iterator iter; vector::difference_type count;

  1. <a name="xsvST"></a>
  2. ## 构造函数
  3. ```cpp
  4. C c; //默认构造函数,构造空容器
  5. C c1(c2); //构造c2的拷贝,也就是c1
  6. C c1 = c2; //如果是array还必须大小相同
  7. C c(b, e); //构造两个迭代器b、e之间的拷贝,array不支持
  8. //容器之间类型可以不同,元素类型也可以不同(能转换)
  9. C c{a, b, c...}; //列表初始化,隐含指定了容器大小。
  10. C c = {a, b, c...}; //如果是array,数量=容器大小,数量不能超,少了值初始化(默认构造)。
  11. //只有顺序容器(除array)构造函数才接受大小参数
  12. C seq(n); //n个元素,值初始化,元素类型必须支持默认初始化,explicit
  13. C seq(n, t); //n个值为t的元素
  14. /********************例子************************/
  15. list<string> ls;
  16. vector<const char*> vcc;
  17. list<string> ls1(ls); //正确,类型和元素类型要匹配
  18. deque<string> ds(ls); //错误:容器类型不匹配
  19. vector<string> vs(ls); //错误:容器类型不匹配
  20. list<const char*> lcc; //错误:元素类型不匹配
  21. forward_list<string> fls(vcc.begin(),vcc.end()); //正确,元素可转换。
  22. array<int, 10> ial; //10个默认初始化的int
  23. array<int, 10> ia2 = (0,1,2,3,4,5,6,7,8,9); //列表初始化
  24. array<int, 10> ia3 = {42}; //ia3[0]为42, 剩余元素为0
  25. vector<int> ivec(10 , -1); //10 个 int 元素,每个都初始化为-1
  26. list<string> svec(10,"hi!"); //10 个 strings; 每个都初始化为“hi!"
  27. forward_list<int> ivec(10); //10 个元素,每个都初始化为 0
  28. deque<string> svec(10); //10 个元素,每个都是空string
  29. array<int, 10>::size_type i; //array必须指定元素类型、数量
  30. array<int>::size_type j; //错误:array<int>不是一个类型

赋值

  1. //赋值:元素类型必须相同,会让c1的内部迭代器、指针、引用失效
  2. c1 = c2; //赋值替换:c1的元素替换为c2
  3. c1 = {a, b, c...}; //赋值替换:c1的元素替换为列表元素,array不适用。
  4. //赋值:仅适合顺序容器,元素类型能转换即可。
  5. seq.assign(b, e); //范围替换,b、e不能指向seq
  6. seq.assign(il); //赋值替换:il是初始化列表
  7. seq.assign(n, t); //赋值替换:n个值为t的元素

swap

  1. //交换:不会让a的内部迭代器、引用、指针失效,但是string、array的会失效。
  2. //交换只是改变a、b数据结构,并未拷贝,所以比拷贝赋值快得多。
  3. //string、array是真正拷贝元素,所以上面的会失效。
  4. a.swap(b); //a、b元素交换,类型必须相同,早期是这个成员函数版本。
  5. swap(a, b); //同上等价,推荐使用这个。
  6. iterator first = a.begin();
  7. swap(a, b); //first没有失效,但是first指向了b.begin()

大小

  1. c.size(); //size_type,元素数目,不支持forward_list
  2. c.max_size(); //size_type,可保存最大数目
  3. c.empty(); //是否空

插入、删除

  1. //array不支持,不同容器,这些接口会不同。
  2. c.insert(args) //args拷贝进c
  3. c.emplace(inits) //inits构造C中的一个元素
  4. c.erase(args) //删除args指定元素
  5. c.clear() //清空容器,返回void

关系运算

  1. //容器必须相同,元素必须相同。
  2. //实质:元素逐个进行关系运算,所以元素必须支持相应的关系运算,可参考string的关系运算。
  3. ==, != //容器是否相等、不相等,所有容器都支持
  4. < , <=, >, >= //无序、关联容器不支持
  5. a == b //true:大小相同 && 元素数量相等
  6. a <= b //逐个运算,a的全部元素都<=b元素。
  7. vector<int> v1 = {1, 3, 5, 7, 9, 12};
  8. vector<int> v2 = {1, 3, 9};
  9. vector<int> v3 = {1, 3, 5, 7 };
  10. vector<int> v4 = {1, 3, 5, 7, 9, 12};
  11. v1 < v2 //true: vl和v2在元素[2]处不同:vl[2]小于等于v2[2]
  12. v1 < v3 //false: 所有元素都相等,但v3中元素数目更少
  13. v1 == v4 //true: 每个元素都相等,且vl和v4大小相同
  14. v1 == v2 //false: v2元素数目比vl少

获取迭代器

迭代器范围(range)是标准库的基础,由 [ begin、end ) 组成,注意是左闭右开区间,并没有包含end。为什么用左闭合,因为:

  • begin == end,为空。
  • begin != end,迭代结束标记 ```cpp c.begin(), c.end() //首尾迭代器,尾是指向最后一个元素的后面。 c.cbegin(), c.cend() //只读首尾迭代器。

list::iterator it5 = a.begin(); //这是没有auto之前的写法 list::const_iterator it6 = a.begin(); //麻烦的写法 auto it7 = a.begin(); //取决于a是不是const auto it8 = a.cbegin(); //const_iterator

  1. <a name="hJoVe"></a>
  2. ## 反向容器
  3. ```cpp
  4. //forward_list不支持
  5. reverse_iterator //按逆序寻址元素的迭代器
  6. const_reverse_iterator //上面的const版
  7. c.rbegin() //返回指向尾元素的迭代器
  8. c.rend() //返回指向首元素前面位置的迭代器
  9. c.crbegin(), c.crend() //上面的const版