C++ 命名要求: SequenceContainer
来自 cppreference.cn
A SequenceContainer 是一种 Container,它以线性排列方式存储相同类型的对象。
目录 |
[编辑] 要求
给定以下类型和值
类型 | 定义 |
C
|
一个序列容器类 |
T
|
C 的元素类型 |
A
|
C 的分配器类型
|
R (自 C++23 起) |
一种模型为 container-compatible-range <T> |
Args (自 C++11 起) |
一个模板参数包 |
Iter
|
C::iterator
|
Ref
|
C::reference
|
CRef
|
C::const_reference
|
Value | 定义 |
v | 类型为 C 的值 |
cv | 类型为 const C 的值 |
i, j | LegacyInputIterator,使得 [ i, j) 是一个有效范围,并且迭代器引用隐式转换为 C::value_type 的元素 |
rg (自 C++23 起) | 类型为 R 的值 |
il (自 C++11 起) | 类型为 std::initializer_list<C::value_type> 的值 |
n | 类型为 C::size_type 的值 |
p | 指向 v 的有效 const 迭代器 |
q | 指向 v 的有效可解引用 const 迭代器 |
q1, q2 | 指向 v 的 const 迭代器,使得 [ q1, q2) 是一个有效范围 |
t | 一个值(直到 C++11)类型为 C::value_type 的左值或 const 右值(自 C++11 起) |
rv (自 C++11 起) | 类型为 C::value_type 的非 const 右值 |
args (自 C++11 起) | 一个具有模式 Arg&& 的函数参数包 |
如果满足以下所有条件,则 C
满足 SequenceContainer 的要求
-
C
满足 Container 的要求。 - 以下语句和表达式是良构的,并具有指定的语义
基本操作 (标准库中所有序列容器的要求,除了 std::array 之外(自 C++11 起)) | |||
---|---|---|---|
语句 | 语义[1] | ||
C c(n, t); | 效果 | 构造一个序列容器,其中包含 n 个 t 的副本。 | |
前提条件 |
| ||
后置条件 | std::distance(c.begin(), c.end()) 为 n。 | ||
C c(i, j); | 效果 | 构造一个序列容器,该容器逐元素等于范围 [ i, j) 。
| |
前提条件 |
| ||
后置条件 | std::distance(c.begin(), c.end()) 为 std::distance(i, j)。 | ||
表达式 | 类型 | 语义 | |
C(std::from_range, rg) (自 C++23 起) |
C
|
效果 | 构造一个序列容器,该容器逐元素等于范围 rg。
|
前提条件 | T 是 EmplaceConstructible 到 X 中,从 *ranges::begin(rg)。 | ||
后置条件 | std::distance(begin(), end()) 为 ranges::distance(rg)。 | ||
C(il) (自 C++11 起) |
C
|
等价于 C(il.begin(), il.end())。 | |
v = il (自 C++11 起) |
C&
|
效果 | 将由 il 表示的范围赋值给 v。[2] |
返回值 | *this | ||
前提条件 | T 是 CopyInsertable 到 C 中且 CopyAssignable。 | ||
后置条件 | v 的现有元素要么被销毁,要么被赋值。 | ||
v.emplace(p, args) (自 C++11 起) |
Iter |
效果 | 在 p 之前插入类型为 T 的对象,该对象使用 std::forward<Args>(args)... 构造。 |
返回值 | 一个迭代器,指向从 args 构造到 v 中的新元素。 | ||
前提条件 | T 是 EmplaceConstructible 到 C 中,从 args。 | ||
v.insert(p, t) | Iter
|
效果 | 在 p 之前插入 t 的副本。 |
返回值 | 一个迭代器,指向插入到 v 中的 t 的副本。 | ||
前提条件 |
| ||
v.insert(p, rv) (自 C++11 起) |
Iter
|
效果 | 在 p 之前插入 rv 的副本,可能使用移动语义。 |
返回值 | 一个迭代器,指向插入到 v 中的 rv 的副本。 | ||
前提条件 | T 是 MoveInsertable 到 C 中的。 | ||
v.insert(p, n, t) | Iter
|
效果 | 在 p 之前插入 n 个 t 的副本。 |
返回值 | 一个迭代器,指向插入到 v 中的第一个元素的副本,如果 n 为 0,则为 p。 | ||
前提条件 |
| ||
v.insert(p, i, j) | Iter
|
效果 | 在 p 之前插入范围 [ i, j) 中元素的副本。
|
返回值 | 一个迭代器,指向插入到 v 中的第一个元素的副本,如果 i == j 为 true,则为 p。 | ||
前提条件 |
| ||
v.insert_range(p, rg) (自 C++23 起) |
Iter
|
效果 | 在 p 之前插入 rg 中元素的副本。
|
返回值 | 一个迭代器,指向插入到 v 中的第一个元素的副本,如果 rg 为空,则为 p。 | ||
前提条件 |
| ||
v.insert(p, il) (自 C++11 起) |
Iter
|
等价于 v.insert(p, il.begin(), il.end())。 | |
v.erase(q) | Iter
|
效果 | 擦除 q 指向的元素。 |
返回值 | 一个迭代器,指向在元素被擦除之前紧随 q 的元素,如果不存在这样的元素,则为 v.end()。 | ||
v.erase(q1, q2) | Iter
|
效果 | 擦除范围 [ q1, q2) 中的元素。 |
返回值 | 一个迭代器,指向在任何元素被擦除之前 q2 指向的元素,如果不存在这样的元素,则为 v.end()。 | ||
v.clear() | void | 效果 | 销毁 v 中的所有元素。
|
后置条件 | v.empty() 为 true。 | ||
复杂度 | 线性。 | ||
v.assign(i, j) | void | 效果 | 用 [ i, j) 的副本替换 v 中的元素。
|
前提条件 |
| ||
v.assign_range(rg) (自 C++23 起) |
void | 效果 | 用 rg 中每个元素的副本替换 v 中的元素。
|
前提条件 |
| ||
v.assign(il) (自 C++11 起) |
void | 等价于 v.assign(il.begin(), il.end())。 | |
v.assign(n, t) | void | 效果 | 用 n 个 t 的副本替换 v 中的元素。 |
前提条件 |
| ||
额外操作[3] (仅对指定的序列容器要求,省略 std:: )
| |||
表达式 | 类型 | 语义 | |
v.front() | Ref
|
容器 | basic_string, array, vector, inplace_vector, deque, list, forward_list
|
返回值 | *v.begin() | ||
cv.front() | CRef
|
容器 | basic_string, array, vector, inplace_vector, deque, list, forward_list
|
返回值 | *cv.begin() | ||
v.back() | Ref
|
容器 | basic_string, array, vector, inplace_vector, deque, list
|
等价于 auto tmp = v.end(); --tmp; return *tmp;[4]。 | |||
cv.back() | CRef
|
容器 | basic_string, array, vector, inplace_vector, deque, list
|
等价于 auto tmp = cv.end(); --tmp; return *tmp;[5]。 | |||
v.emplace_front(args) (自 C++11 起) |
void | 容器 | deque, list, forward_list
|
效果 | 前置一个类型为 T 的对象,该对象使用 std::forward<Args>(args)... 构造。 | ||
返回值 | v.front() | ||
前提条件 | T 是 EmplaceConstructible 到 C 中,从 args。 | ||
v.emplace_back(args) (自 C++11 起) |
void | 容器 | vector, inplace_vector, deque, list
|
效果 | 追加一个类型为 T 的对象,该对象使用 std::forward<Args>(args)... 构造。 | ||
返回值 | v.back() | ||
前提条件 | T 是 EmplaceConstructible 到 C 中,从 args。 | ||
v.push_front(t) | void | 容器 | deque, list, forward_list
|
效果 | 前置 t 的副本。 | ||
前提条件 |
| ||
v.push_front(rv) (自 C++11 起) |
void | 容器 | deque, list, forward_list
|
效果 | 前置 rv 的副本,可能使用移动语义。 | ||
前提条件 | T 是 MoveInsertable 到 C 中的。 | ||
v.prepend_range(rg) (自 C++23 起) |
void | 容器 | deque, list, forward_list
|
效果 | 在 [6] v.begin() 之前插入 rg 中元素的副本。
| ||
前提条件 | T 是 EmplaceConstructible 到 C 中,从 *ranges::begin(rg)。 | ||
v.push_back(t) | void | 容器 | basic_string, array, vector, inplace_vector, deque, list
|
效果 | 追加 t 的副本。 | ||
前提条件 |
| ||
v.push_back(rv) (自 C++11 起) |
void | 容器 | basic_string, array, vector, inplace_vector, deque, list
|
效果 | 追加 rv 的副本,可能使用移动语义。 | ||
前提条件 | T 是 MoveInsertable 到 C 中的。 | ||
v.append_range(rg) (自 C++23 起) |
void | 容器 | vector, inplace_vector, deque, list
|
效果 | 在 [6] v.end() 之前插入 rg 中元素的副本。
| ||
前提条件 | T 是 EmplaceConstructible 到 C 中,从 *ranges::begin(rg)。 | ||
v.pop_front() | void | 容器 | deque, list, forward_list
|
效果 | 销毁第一个元素。 | ||
前提条件 | a.empty() 为 false。 | ||
v.pop_back() | void | 容器 | basic_string, array, vector, inplace_vector, deque, list
|
效果 | 销毁最后一个元素。 | ||
前提条件 | a.empty() 为 false。 | ||
v[n] | Ref
|
容器 | basic_string, array, vector, inplace_vector, deque
|
等价于 return *(v.begin() + n);。 | |||
cv[n] | CRef
|
容器 | basic_string, array, vector, inplace_vector, deque
|
等价于 return *(cv.begin() + n);。 | |||
v.at(n) | Ref
|
容器 | basic_string, array, vector, inplace_vector, deque
|
返回值 | *(v.begin() + n) | ||
异常 | 如果 n >= v.size() 为 true,则抛出 std::out_of_range。 | ||
cv.at(n) | CRef
|
容器 | basic_string, array, vector, inplace_vector, deque
|
返回值 | *(cv.begin() + n) | ||
异常 | 如果 n >= cv.size() 为 true,则抛出 std::out_of_range。 | ||
注释 | |||
|
此外,对于每个序列容器
- 如果相应的模板参数不满足 LegacyInputIterator,则接受两个输入迭代器的构造函数模板以及接受两个输入迭代器的
insert
、append
、assign
、replace
成员函数模板重载不参与重载解析。
|
(自 C++17 起) |
[编辑] 标准库
以下标准库字符串类型和容器满足 SequenceContainer 的要求
存储和操作字符序列 (类模板) | |
(C++11) |
固定大小的就地连续数组 (类模板) |
可调整大小的连续数组 (类模板) | |
(C++26) |
可调整大小、固定容量的就地连续数组 (类模板) |
双端队列 (类模板) | |
(C++11) |
单链表 (类模板) |
双链表 (类模板) |
[编辑] 用法说明
Container | 优点 | 缺点 |
---|---|---|
std::vector | 快速访问,连续存储 | 大多数情况下插入/删除效率低下 |
std::inplace_vector | 快速访问,就地连续存储 | 固定容量且大多数情况下插入/删除效率低下 |
std::array | 快速访问,就地连续存储 | 元素数量固定且没有插入/删除 |
std::deque | 快速访问,在开头/结尾高效插入/删除 | 在序列中间插入/删除效率低下 |
std::list std::forward_list |
在序列中间高效插入/删除 | 访问主要是线性时间 |
[编辑] 缺陷报告
以下行为变更缺陷报告已追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 已发布时的行为 | 正确的行为 |
---|---|---|---|
LWG 139 | C++98 | 可选操作不是必需的 为指定的容器实现 |
要求使用摊销时间 |
LWG 149 | C++98 | v.insert(p, t) 返回 Iter ,而v.insert(p, n, t) 和 v.insert(p, n, t) 返回 void |
它们都返回 Iter |
LWG 151 | C++98 | q1 曾被要求是可解引用的[1] | 它可以是不可解引用的 |
LWG 355 | C++98 | 调用 v.back() 或 v.pop_back() 将会 执行 --v.end(),这是危险的[2] |
递减一个副本 而不是 v.end() |
LWG 589 | C++98 | i 和 j 指向的元素 可能无法转换为 C::value_type |
它们是隐式地 可转换为 C::value_type |
LWG 2194 | C++11 | std::queue、 std::priority_queue 和 std::stack 也曾是 SequenceContainers[3] |
它们不是 SequenceContainers |
LWG 2231 | C++11 | v.clear() 的复杂度要求 在 C++11 中被错误地遗漏了 |
复杂度被重申为线性 |
LWG 3927 | C++98 | operator[] 没有隐式要求 | 添加了隐式要求 |