C++ 命名需求: SequenceContainer
来自 cppreference.com
一个 SequenceContainer 是一个 Container,它以线性排列方式存储相同类型的对象。
内容 |
[编辑] 需求
图例 | |
X
|
一个顺序容器类 |
T
|
X 的元素类型 |
a | X 类型的值 |
u | 已声明变量的名称 |
A
|
X 的分配器类型
|
i, j | LegacyInputIterators,使得 [ i, j) 是一个有效的范围,并且迭代器引用隐式可转换为 value_type 的元素。 |
rg (自 C++23 起) | 类型 R 的值,该类型模拟 container-compatible-range<T> 。 |
il (自 C++11 起) | 类型 std::initializer_list<value_type> 的对象。 |
n | 类型 X::size_type 的值。 |
p | 一个指向 a 的有效 const 迭代器。 |
q | 一个指向 a 的有效可解引用的 const 迭代器。 |
q1, q2 | 指向 a 的两个 const 迭代器,使得 [ q1, q2) 是一个有效的范围。 |
t | 类型 X::value_type 的 左值 或 const 右值(自 C++11 起)。 |
rv (自 C++11 起) | 类型 X::value_type 的非 const 右值。 |
Args (自 C++11 起) |
一个模板参数包。 |
args (自 C++11 起) | 一个具有模式 Arg&& 的函数参数包。 |
类型 X
满足 SequenceContainer,如果
- 类型
X
满足 Container,并且 - 以下语句和表达式对于所有顺序容器 除 std::array (见 说明)(自 C++11 起) 必须有效,并具有指定的效用。
语句 | 效用 | 条件[1] | ||
---|---|---|---|---|
X u(n, t) | 构造包含 n 个 t 副本的顺序容器。 | 前提 | T 是 CopyInsertable 到 X 中的。 | |
后置 | std::distance(u.begin(), u.end()) == n | |||
X u(i, j) | 构造与范围 [ i, j) 元素相等的顺序容器。 |
前提 | T 是 EmplaceConstructible 从 *i 到 X 中的。 | |
后置 | std::distance(u.begin(), u.end()) == std::distance(i, j) | |||
表达式 | 类型 | 效用 | 条件 | |
X(std::from_range, rg) (自 C++23 起) |
X
|
构造与范围 rg 元素相等的顺序容器。 | 前提 | T 是 EmplaceConstructible 从 *ranges::begin(rg) 到 X 中的。 |
后置 |
| |||
X(il) (自 C++11 起) |
X
|
等效于 X(il.begin(), il.end()) |
没有显式需求。 | |
a = il (自 C++11 起) |
X&
|
将 il 表示的范围赋值到 a 中。[2] | 前提 | T 是 CopyInsertable 和 CopyAssignable。 |
后置 | a 中的现有元素被销毁或赋值。 | |||
a.emplace(p, args) (自 C++11 起) |
iterator
|
在 p 之前插入一个类型为 T 的对象,使用 std::forward<Args>(args) 构造。 |
前提 | T 是 EmplaceConstructible。 |
后置 | 返回的迭代器指向从 args 构造到 a 中的元素。 | |||
a.insert(p, t) | iterator
|
在 p 之前插入 t 的副本。 | 前提 | T 是 CopyInsertable。 |
后置 | 返回的迭代器指向插入到 a 中的 t 的副本。 | |||
a.insert(p, rv) (自 C++11 起) |
iterator
|
在 p 之前插入 rv 的副本,可能使用移动语义。 | 前提 | T 是 MoveInsertable。 |
后置 | 返回的迭代器指向插入到 a 中的 rv 的副本。 | |||
a.insert(p, n, t) | iterator
|
在 p 之前插入 n 个 t 的副本。 | 前提 | T 是 CopyInsertable 和 CopyAssignable。 |
后置 | 返回的迭代器指向插入到 a 中的第一个元素的副本,或者当 n == 0 时为 p。 | |||
a.insert(p, i, j) | iterator
|
插入元素的副本[ i, j) 在 p 之前。 |
前提 | T 是 EmplaceConstructible,并且 i 和 j 不在 a 中。 |
后置 |
| |||
a.insert_range(p, rg) (自 C++23 起) |
iterator
|
在 p 之前插入 rg 中元素的副本。 | 前提 |
|
后置 |
| |||
a.insert(p, il) (自 C++11 起) |
iterator
|
等效于 a.insert(p, il.begin(), il.end()) |
前提 | 没有显式需求。 |
后置 | 返回的迭代器指向插入到 a 中的第一个元素的副本,或者如果 il 为空,则指向 p。 | |||
a.erase(q) | iterator
|
删除 q 指向的元素。 | 前提 | 没有显式需求。 |
后置 | 返回的迭代器指向在删除之前紧随 q 的元素,或者如果不存在这样的元素,则指向 a.end()。 | |||
a.erase(q1, q2) | iterator
|
删除 [ q1, q2) 中的元素。 |
前提 | 没有显式需求。 |
后置 | 返回的迭代器指向在任何删除之前由 q2 指向的元素,或者如果不存在这样的元素,则指向 a.end()。 | |||
a.clear() | void | 销毁 a 中的所有元素。 | 前提 | 没有显式需求。 |
后置 |
| |||
a.assign(i, j) | void | 用 [ i, j) 的副本替换 a 中的元素。 |
前提 |
|
后置 | [ i, j) 中的每个迭代器都被解引用一次。 | |||
a.assign_range(rg) (自 C++23 起) |
void | 用 rg 中每个元素的副本替换 a 中的元素。 | 前提 |
|
后置 |
| |||
a.assign(il) (自 C++11 起) |
void | 等效于 a.assign(il.begin(), |
没有显式需求。 | |
a.assign(n, t) | void | 用 n 个 t 的副本替换 a 中的元素。 | 前提 | T 是 CopyInsertable 和 CopyAssignable。 |
后置 | 没有显式需求。 | |||
注释 | ||||
|
[edit] 可选操作
以下表达式对于命名的序列容器必须有效并具有其指定的效果,所有操作 除了 prepend_range
和 append_range
(自 C++23 起) 占用摊销常数时间。
表达式 | 类型 | 效用 | 先决条件[1] | 容器 |
---|---|---|---|---|
a.front() | reference ,或者对于 const a 为 |
返回 *a.begin()。 | 没有显式需求。 | std::basic_string,std::array,std::deque,std::forward_list,std::inplace_vector,std::list,std::vector |
a.back() | reference ,或者对于 const a 为 |
等效于 auto tmp = a.end(); --tmp; return *tmp; |
没有显式需求。 | std::basic_string,std::array,std::deque,std::inplace_vector,std::list,std::vector |
a.emplace_front(args) (自 C++11 起) |
void | 在开头添加一个使用 std::forward<Args> (args)... 构造的 T 。 |
T 是 EmplaceConstructible,可以从 args 构建到 X 中。 |
std::deque,std::forward_list,std::list |
a.emplace_back(args) (自 C++11 起) |
void | 使用 std::forward<Args> (args)... 构造的 T 追加到末尾。 |
T 是 EmplaceConstructible,可以从 args 构建到 X 中。 |
std::deque, std::inplace_vector, std::list, std::vector |
a.push_front(t) | void | 在容器头部追加 t 的副本。 | T 是 CopyInsertable 到 X 中的。 |
std::deque,std::forward_list,std::list |
a.push_front(rv) (自 C++11 起) |
void | 在容器头部追加 rv 的副本,可能使用移动语义。 | T 是 MoveInsertable 到 X 中。 | |
a.prepend_range(rg) (自 C++23 起) |
void | 在 begin() 之前插入 [2] rg 中元素的副本,rg 中的每个迭代器都被解引用一次。 | T 是 EmplaceConstructible 从 *ranges::begin(rg) 到 X 中的。 |
std::deque,std::forward_list,std::list |
a.push_back(t) | void | 在容器尾部追加 t 的副本。 | T 是 CopyInsertable 到 X 中的。 |
std::basic_string, std::deque, std::inplace_vector, std::list, std::vector |
a.push_back(rv) (自 C++11 起) |
void | 在容器尾部追加 rv 的副本,可能使用移动语义。 | T 是 MoveInsertable 到 X 中。 | |
a.append_range(rg) (自 C++23 起) |
void | 在 end() 之前插入 [2] rg 中元素的副本,每个迭代器都被解引用一次。 | T 是 EmplaceConstructible 从 *ranges::begin(rg) 到 X 中的。 |
std::deque, std::inplace_vector, std::list, std::vector |
a.pop_front() | void | 销毁第一个元素。 | a.empty() 为 false | std::deque,std::forward_list,std::list |
a.pop_back() | void | 销毁最后一个元素。 | a.empty() 为 false | std::basic_string, std::deque, std::inplace_vector, std::list, std::vector |
a[n] | reference ,或者对于 const a 为 |
返回 *(a.begin() + n) | 没有显式需求。 | std::basic_string, std::array, std::deque, std::inplace_vector, std::vector |
a.at(n) | reference ,或者对于 const a 为 |
返回 *(a.begin() + n),如果 n >= size() 则抛出 std::out_of_range | 没有显式需求。 | |
备注 | ||||
此外,对于每个序列容器
- 如果相应的模板参数不满足 LegacyInputIterator,则接受两个输入迭代器的构造函数模板以及
insert
、append
、assign
、replace
的成员函数模板重载,这些重载接受两个输入迭代器,将不会参与重载解析。
|
(自 C++17 起) |
[edit] 标准库中的序列容器
存储和操作字符序列 (类模板) | |
(C++11) |
固定大小的原地连续数组 (类模板) |
动态连续数组 (类模板) | |
(C++26) |
动态可调整大小、固定容量、原地连续数组 (类模板) |
双端队列 (类模板) | |
(C++11) |
单链表 (类模板) |
双链表 (类模板) |
[edit] 权衡/使用说明
std::vector | 快速访问,但插入/删除效率大多很低。 |
std::inplace_vector | 快速访问,原地连续存储,但容量固定且插入/删除效率大多很低。 |
std::array | 快速访问,原地连续存储,但元素数量固定且无法插入/删除。 |
std::deque | 快速访问,在序列开头/结尾处高效插入/删除,但在中间位置效率不高。 |
std::list std::forward_list |
在序列中间高效插入/删除,但访问大多是线性时间。 |
[edit] 缺陷报告
以下行为变更缺陷报告被追溯应用于之前发布的 C++ 标准。
DR | 应用于 | 发布的行为 | 正确行为 |
---|---|---|---|
LWG 139 | C++98 | 可选操作不需要 在指定的容器中实现 |
需要,并以 摊销时间 |
LWG 149 | C++98 | a.insert(p, t) 返回 iterator 而a.insert(p, n, t) 和 a.insert(p, n, t) 返回 void |
它们都返回iterator
|
LWG 151 | C++98 | q1 需要可解引用 [1] | 它可以不可解引用 |
LWG 355 | C++98 | 调用 a.back() 或 a.pop_back() 会 执行 --a.end(),这是危险的 [2] |
递减一个副本 而不是 a.end() |
LWG 589 | C++98 | i 和 j 所引用的元素 可能无法转换为 value_type |
它们是隐式地 可转换为 value_type |
LWG 3927 | C++98 | operator[] 没有隐式要求 | 添加了隐式要求 |