C++ 命名要求: SequenceContainer
来自 cppreference.cn
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
|
值 | 定义 |
v | 类型为 C 的值 |
cv | 类型为 const C 的值 |
i, j | LegacyInputIterators,使得 [ 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::value_type 的值(直到 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 可以从 *ranges::begin(rg) EmplaceConstructible 到 X 中。 | ||
后置条件 | 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 之前插入一个用 std::forward<Args>(args)... 构造的 T 类型对象。 |
返回值 | 指向从 args 构造到 v 中的新元素的迭代器。 | ||
前置条件 | T 可以从 args EmplaceConstructible 到 C 中。 | ||
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 | 效果 | 将 v 中的元素替换为范围 [ i, j) 的副本。
|
前置条件 |
| ||
v.assign_range(rg) (C++23 起) |
void | 效果 | 将 v 中的元素替换为 rg 中每个元素的副本。
|
前置条件 |
| ||
v.assign(il) (C++11 起) |
void | 等价于 v.assign(il.begin(), il.end())。 | |
v.assign(n, t) | void | 效果 | 将 v 中的元素替换为 n 个 t 的副本。 |
前置条件 |
| ||
额外操作[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
|
效果 | 预先添加一个用 std::forward<Args>(args)... 构造的 T 类型对象。 | ||
返回值 | v.front() | ||
前置条件 | T 可以从 args EmplaceConstructible 到 C 中。 | ||
v.emplace_back(args) (C++11 起) |
void | 容器 | vector, inplace_vector, deque, list
|
效果 | 追加一个用 std::forward<Args>(args)... 构造的 T 类型对象。 | ||
返回值 | v.back() | ||
前置条件 | T 可以从 args EmplaceConstructible 到 C 中。 | ||
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
|
效果 | 在 v.begin() 之前[6] 插入 rg 中元素的副本。
| ||
前置条件 | T 可以从 *ranges::begin(rg) EmplaceConstructible 到 C 中。 | ||
v.push_back(t) | void | 容器 | basic_string, vector, inplace_vector, deque, list
|
效果 | 追加 t 的一个副本。 | ||
前置条件 |
| ||
v.push_back(rv) (C++11 起) |
void | 容器 | basic_string, vector, inplace_vector, deque, list
|
效果 | 追加 rv 的一个副本,可能使用移动语义。 | ||
前置条件 | T 可以 MoveInsertable 到 C 中。 | ||
v.append_range(rg) (C++23 起) |
void | 容器 | vector, inplace_vector, deque, list
|
效果 | 在 v.end() 之前[6] 插入 rg 中元素的副本。
| ||
前置条件 | T 可以从 *ranges::begin(rg) EmplaceConstructible 到 C 中。 | ||
v.pop_front() | void | 容器 | deque, list, forward_list
|
效果 | 销毁第一个元素。 | ||
前置条件 | a.empty() 为 false。 | ||
v.pop_back() | void | 容器 | basic_string, 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。 | ||
注意 | |||
|
此外,对于每个序列容器:
- 接受两个输入迭代器的构造函数模板以及接受两个输入迭代器的
insert
、append
、assign
、replace
成员函数模板重载,如果相应的模板参数不满足 LegacyInputIterator,则不参与重载决议。
|
(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++ 标准。
缺陷报告 | 应用于 | 发布时的行为 | 正确的行为 |
---|---|---|---|
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[] 没有隐式要求 | 添加了隐式要求 |