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