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