容器库是一个通用的类模板和算法集合,允许程序员轻松地实现常见的數據结构,例如队列、列表和栈。有两种(C++11之前)三种(C++11之后)容器类
它们中的每一个都旨在支持一组不同的操作。
容器管理为其元素分配的存储空间,并提供成员函数来访问这些元素,可以直接访问,也可以通过迭代器(具有类似指针属性的对象)访问。
大多数容器至少有一些共同的成员函数,并共享功能。哪种容器最适合特定应用程序不仅取决于提供的功能,还取决于它对不同工作负载的效率。
[编辑] 序列容器
序列容器实现可以按顺序访问的數據结构。
[编辑] 关联容器
关联容器实现可以快速搜索的排序數據结构(O(log n) 复杂度)。
|
按键排序的唯一键集合 (类模板) [编辑] |
|
按键排序的键值对集合,键是唯一的 (类模板) [编辑] |
|
按键排序的键集合 (类模板) [编辑] |
|
按键排序的键值对集合 (类模板) [编辑] |
[编辑] 无序关联容器 (C++11之后)
无序关联容器实现可以快速搜索的无序(哈希)數據结构(O(1) 平均,O(n) 最坏情况复杂度)。
|
按键哈希的唯一键集合 (类模板) [编辑] |
|
按键哈希的键值对集合,键是唯一的 (类模板) [编辑] |
|
按键哈希的键集合 (类模板) [编辑] |
|
按键哈希的键值对集合 (类模板) [编辑] |
[编辑] 容器适配器
容器适配器为序列容器提供不同的接口。
|
适配容器以提供栈(后进先出数据结构) (类模板) [编辑] |
|
适配容器以提供队列(先进先出数据结构) (类模板) [编辑] |
|
适配容器以提供优先队列 (类模板) [编辑] |
|
适配容器以提供按键排序的唯一键集合 (类模板) [编辑] |
|
适配两个容器以提供按唯一键排序的键值对集合 (类模板) [编辑] |
|
适配容器以提供按键排序的键集合 (类模板) [编辑] |
|
适配两个容器以提供按键排序的键值对集合 (类模板) [编辑] |
[编辑] 视图
视图提供灵活的设施来与一维或多维的非拥有数组元素视图进行交互。
|
对连续对象序列的非拥有视图 (类模板) [编辑] |
|
多维非拥有数组视图 (类模板) [编辑] |
[编辑] 迭代器失效
只读方法永远不会使迭代器或引用失效。修改容器内容的方法可能会使迭代器和/或引用失效,如该表所总结。
类别 |
容器 |
在插入后,是否... |
在擦除后,是否... |
有条件地 |
迭代器有效? |
引用有效? |
迭代器有效? |
引用有效? |
序列容器 |
数组
|
不适用
|
不适用
|
|
向量
|
否 |
不适用
|
插入改变了容量 |
是 |
是 |
在修改的元素之前 (仅在容量未改变的情况下插入) |
否 |
否 |
在或之后修改元素 |
双端队列
|
否 |
是 |
是,除了已删除的元素 |
修改了第一个或最后一个元素 |
否 |
否 |
仅修改中间部分 |
双向链表
|
是 |
是,除了已删除的元素 |
|
单向链表
|
是 |
是,除了已删除的元素 |
|
关联容器 |
集合 多重集合 映射 多重映射
|
是 |
是,除了已删除的元素 |
|
无序关联容器 |
无序集合 无序多重集合 无序映射 无序多重映射
|
否 |
是 |
不适用
|
插入导致重新散列 |
是 |
是,除了已删除的元素 |
没有重新散列 |
这里,插入 指的是任何将一个或多个元素添加到容器中的方法,而删除 指的是任何从容器中删除一个或多个元素的方法。
除非另有说明(明确说明或通过根据其他函数定义函数),否则将容器作为参数传递给库函数永远不会使指向该容器中对象的迭代器失效,也不会更改该容器中对象的的值。
尾后迭代器值得特别一提。通常情况下,该迭代器会失效,就好像它是一个指向未删除元素的普通迭代器一样。因此,std::set::end 从未失效, std::unordered_set::end 仅在重新散列时失效(自 C++11 起),std::vector::end 始终失效(因为它始终在修改的元素之后),依此类推。
有一个例外:删除 std::deque 的最后一个元素的删除操作确实会使尾后迭代器失效,即使它不是容器的已删除元素(或任何元素)。结合 std::deque 迭代器的常规规则,最终结果是,唯一不会使 std::deque::end 失效的修改操作是删除第一个元素但不删除最后一个元素的删除操作。
线程安全性
- 所有容器函数都可以由不同线程在不同容器上并发调用。更一般地说,C++ 标准库函数不会读取其他线程可访问的对象,除非这些对象可以通过函数参数(包括 this 指针)直接或间接访问。
- 所有 const 成员函数都可以由不同线程在同一个容器上并发调用。此外,成员函数
begin() 、end() 、rbegin() 、rend() 、front() 、back() 、data() 、find() 、lower_bound() 、upper_bound() 、equal_range() 、at() 以及(除了关联容器之外)operator[] 在线程安全性的目的上表现得像 const(也就是说,它们也可以由不同线程在同一个容器上并发调用)。更一般地说,C++ 标准库函数不会修改对象,除非这些对象可以通过函数的非 const 参数(包括 this 指针)直接或间接访问。 - 同一个容器中的不同元素可以由不同线程并发修改,但 std::vector<bool> 的元素除外(例如,std::future 对象的向量可以从多个线程接收值)。
- 迭代器操作(例如,递增迭代器)读取底层容器,但不会修改底层容器,并且可以与同一个容器上的其他迭代器的操作、const 成员函数或元素的读取并发执行。使任何迭代器失效的容器操作会修改容器,并且不能与现有迭代器上的任何操作并发执行,即使这些迭代器没有失效。
- 同一个容器的元素可以与那些未指定访问这些元素的成员函数并发修改。更一般地说,C++ 标准库函数不会读取间接通过其参数(包括容器的其他元素)访问的对象,除非其规范要求这样做。
- 无论如何,容器操作(以及算法或任何其他 C++ 标准库函数)可以在内部并行化,只要这样做不会改变用户可见的结果(例如,std::transform 可以并行化,但 std::for_each 不能并行化,因为它指定按顺序访问序列的每个元素)。
|
(C++11之后) |
注意:std::basic_string 不被标准视为容器,但由于其相似性,其行为与容器非常类似。为了方便起见,这里将其列为“伪容器”。
|
- C++03 中存在的函数 |
|
- C++11 起存在的函数 |
|
- C++17 起存在的函数 |
|
- C++20 起存在的函数 |
|
- C++23 起存在的函数 |
- 注意:两行不同的 extract 中的函数具有不同的含义和语法
- ↑ 例如,node_type extract(const_iterator) 或 node_type extract(Key&)
- ↑ 例如,container_type extract() &&
[edit] 非成员函数表
< 、<= 、> 、>= 和 != 运算符分别从 operator<=> 和 operator== 合成。
|
(自 C++20 起) |
以下行为更改的缺陷报告被追溯应用于以前发布的 C++ 标准。
DR |
应用于 |
发布时的行为 |
正确行为 |
LWG 51
|
C++98 |
容器迭代器可能会失效 通过任意库操作 |
它们仅在 指定的情况下失效 |
[编辑] 另请参见
C++ 命名需求
|
数值数组、数组掩码和数组切片 (类模板) [编辑] |
|
存储和操作字符序列 (类模板) [编辑] |
|
只读字符串视图 (类模板) [编辑] |