容器库
容器库是类模板与算法的汇集,允许程序员简单地访问常见数据结构,例如队列、链表和栈。有两 (C++11 前)三 (C++11 起)类容器:
- 顺序容器
- 关联容器
|
(C++11 起) |
容器管理为其元素分配的存储空间,并提供成员函数来直接或通过迭代器(具有类似于指针的属性的对象)访问它们。
许多容器有几个共同的成员函数,并且共享功能。决定使用哪种类型的容器来满足特定需求通常不仅仅取决于容器提供的功能,还取决于其某些成员的效率(复杂性)。对于序列容器来说尤其如此,它在插入/删除元素和访问它们之间的复杂性上提供了不同的权衡。
顺序容器
顺序容器实现能按顺序访问的数据结构。
(C++11) |
静态的连续数组 (类模板) |
动态的连续数组 (类模板) | |
双端队列 (类模板) | |
(C++11 起) |
单链表 (类模板) |
双链表 (类模板) |
关联容器
关联容器实现能快速查找(O(log n) 复杂度)的数据结构。
唯一键的集合,按照键排序 (类模板) | |
键值对的集合,按照键排序,键是唯一的 (类模板) | |
键的集合,按照键排序 (类模板) | |
键值对的集合,按照键排序 (类模板) |
无序关联容器 (C++11 起)
无序关联容器提供能快速查找(均摊 O(1) ,最坏情况 O(n) 的复杂度)的无序(哈希)数据结构。
(C++11 起) |
唯一键的集合,按照键生成散列 (类模板) |
(C++11 起) |
键值对的集合,按照键生成散列,键是唯一的 (类模板) |
(C++11 起) |
键的集合,按照键生成散列 (类模板) |
(C++11 起) |
键值对的集合,按照键生成散列 (类模板) |
容器适配器
容器适配器不是完整的容器类,而是提供特定接口的类,并依赖于其中一个容器类(例如双端队列或列表)的对象来处理元素。底层容器以这样一种方式封装,即容器适配器的成员独立于所使用的底层容器类来访问其元素。
适配一个容器以提供栈(LIFO 数据结构) (类模板) | |
适配一个容器以提供队列(FIFO 数据结构) (类模板) | |
适配一个容器以提供优先级队列 (类模板) |
span
(C++20 起)
span
是相接的对象序列上的非占有视图,某个其他对象占有序列的存储。
(C++20) |
对象的连续序列上的无所有权视图 (类模板) |
迭代器失效
只读方法决不会使迭代器或引用失效。此表格总结了可能使迭代器和/或引用失效的修改容器内容的方法:
类别 | 容器 | 插入后…… | 擦除后…… | 条件 | ||
---|---|---|---|---|---|---|
迭代器有效? | 引用有效? | 迭代器有效? | 引用有效? | |||
顺序容器 | array | N/A | N/A | |||
vector | 否 | N/A | 插入更改容量 | |||
是 | 是 | 在被修改元素前 | ||||
否 | 否 | 在被修改元素处或元素后 | ||||
deque | 否 | 是 | 是,除了被擦除元素 | 修改首元素或尾元素 | ||
否 | 否 | 只修改中间元素 | ||||
list | 是 | 是,除了被擦除元素 | ||||
forward_list | 是 | 是,除了被擦除元素 | ||||
关联容器 | set | 是 | 是,除了被擦除元素 | |||
无序关联容器 | unordered_set | 否 | 是 | N/A | 插入导致重哈希 | |
是 | 是,除了被擦除元素 | 无重哈希 |
此处插入指代任何添加一或多个元素到容器的方法,而擦除指代任何从容器移除一或多个元素的方法。
|
(C++11 起) |
- 擦除方法的例子是 std::set::erase、std::vector::pop_back、 std::deque::pop_front 和 std::map::clear 。
-
clear
会使所有迭代器和引用失效。因为它会擦除所有元素,这在技术上遵照上述规则。
-
尾后迭代器需要特别留意。通常像指向未被擦除元素的正常迭代器一般使此迭代器失效。所以 std::set::end 永远不会失效,std::unordered_set::end 只有在重哈希时会失效 (C++11 起), std::vector::end 始终会失效(因为它始终在被修改元素后出现),以此类推。
有一个例外:删除 std::deque 末元素的擦除操作会使尾后迭代器失效,尽管它不是容器的被擦除元素(或者说根本不是元素)。与 std::deque 迭代器的通用规则结合后,最终结果是修改操作中只有“删除首元素”(而不是“删除末元素”) 不会 使std::deque::end 失效。
线程安全
|
(C++11 起) |
成员函数表格
- C++03 起存在的函数 | |
- C++11 起存在的函数 | |
- C++17 起存在的函数 | |
- C++20 起存在的函数 |
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
缺陷报告 | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
LWG 51 | C++98 | 容器迭代器可能会由于任意库操作而失效 | 只有在指定情况下会失效 |
参阅
- C++ 具名要求:容器 (Container)
数值数组,数组掩码和数组切分 (类模板) |