# C++ 具名要求：序列容器 (SequenceContainer)

< cpp‎ | named req

序列容器 (SequenceContainer) 是在线性排列中存储相同类型对象的容器 (Container) 。

### 要求

以下情况下，类型 `X` 满足序列容器 (SequenceContainer)

- 类型 `X` 满足容器 (Container) ，且

给定

- `T`，为 `X` 的元素类型
- `A`，为 `X` 的分配器类型：若存在则为 X::allocator_type，否则为 std::allocator<T>
- `a`，为 `X` 类型的左值表达式
- `p`，`a` 中的有效常量迭代器
- `q`，`a` 中的有效可解引用常量迭代器
- `q1` 与 `q2`，为 `a` 中的两个有效常量迭代器，并使得 [q1, q2) 是有效范围
- `i` 与 `j`，为老式输入迭代器 (LegacyInputIterator) ，使得 [i, j) 是有效范围，且各迭代器指代能隐式转换成 `value_type` 的对象
- `il`，为 std::initializer_list<value_type> 类型的对象
- `n`，为 X::size_type 类型的值
- `t`，为 X::value_type 类型的左值或 const 右值
- `rv`，为 X::value_type 类型的非 const 右值
- `Args`：模板形参包
- `args`：拥有模式 Arg&& 的函数形参包

下列表达式必须合法，且对除 std::array 之外的所有顺序容器均具有所指定的效果：

表达式 | 返回类型 | 效果 | 前条件 | 后条件
--- | --- | --- | --- | ---
X(n, t) X a(n, t) |  | 构造保有 `n` 个 `t` 的副本的容器 | `T` 可复制插入 (CopyInsertable) 到 `X` | std::distance(begin(),end()) == n
X(i, j) X a(i, j) |  | 构造与范围 `[i,j)` 逐元素相等的顺序容器 | `T` 从 `*i` 可就位构造 (EmplaceConstructible) 到 `X` 中 (仅对 std::vector)若各迭代器不是老式向前迭代器 (LegacyForwardIterator) ，则 `T` 必须可复制插入 (CopyInsertable) | std::distance(begin(),end()) == std::distance(i,j)
X(il) |  | X(il.begin(), il.end()) |  |
a = il | X& | 将 `il` 所表示的范围赋值到 `a` 中[1] | `T` 可复制插入 (CopyInsertable) 且可复制赋值 (CopyAssignable) | `a` 的既存元素被销毁或被赋值
a.emplace(p,args) | `iterator` | 在 `p` 前插入以 std::forward<Args>(args) 构造的 `T` 类型的对象 | `T` 可复制插入 (CopyInsertable) (对 std::vector 与 std::deque) `T` 可移动赋值 (MoveAssignable) 且可移动插入 (MoveInsertable) | 返回指向由 `args` 构造到 `a` 中的元素的迭代器
a.insert(p,t) | `iterator` | 在 `p` 前插入 `t` 的副本 | `T` 可复制插入 (CopyInsertable) (对 std::vector 与 std::deque) `T` 可复制赋值 (CopyAssignable) 或可移动赋值 (MoveAssignable) | 返回指向插入到 `a` 中的 `t` 的副本的迭代器
a.insert(p,rv) | `iterator` | 在 `p` 前插入 `rv` 的副本，可能用移动语义 | `T` 可移动插入 (MoveInsertable) (对 std::vector 与 std::deque) `T` 可移动赋值 (MoveAssignable) | 返回指向插入到 `a` 中的 `rv` 的副本的迭代器
a.insert(p,n,t) | `iterator` | 插入 `n` 个 `t` 的副本到 `p` 之前 | `T` 可复制插入 (CopyInsertable) 且可复制赋值 (CopyAssignable) | 返回指向插入到 `a` 中的首元素的副本的迭代器，或当 n==0 时为 `p`
a.insert(p,i,j) | `iterator` | 插入 `[i, j)` 中元素的副本到 `p` 之前 | `T` 可就位构造 (EmplaceConstructible) 且 `i` 与 `j` 不在 `a` 中 (仅对 std::vector)若迭代器不是老式向前迭代器 (LegacyForwardIterator) ，则 `T` 必须可移动插入 (MoveInsertable) 且可移动赋值 (MoveAssignable) | `[i,j)` 中的每个迭代器被解引用一次。返回指向插入到 `a` 的首元素的副本的迭代器，或当 i==j 时为 `p`
a.insert(p, il) | `iterator` | a.insert(p,il.begin(),il.end()) |  | 返回指向插入到 `a` 中的首元素的副本的迭代器，或若 `il` 为空则为 `p`。
a.erase(q) | `iterator` | 擦除 `q` 所指向的元素 | (std::deque, std::vector) `T` 可移动赋值 (MoveAssignable) | 返回指向擦除前紧跟 `q` 之后的元素的迭代器，或若此种元素不存在则返回 a.end()。
a.erase(q1,q2) | `iterator` | 擦除 `[q1,q2)` 中的元素 | (std::deque, std::vector) `T` 可移动赋值 (MoveAssignable) | 返回指向在任何擦除前 `q2` 曾指向的元素的迭代器，或若不存在此种元素则返回 a.end()。
a.clear() | `void` | 销毁 `a` 中所有元素 |  | 所有引用、指针及迭代器均失效，包含尾迭代器。a.empty() == true。
a.assign(i,j) | `void` | 以 `[i, j)` 的副本替换 a 中的元素 | `T` 可就位构造 (EmplaceConstructible) ，且 `i`、`j` 不在 `a` 中 (std::vector)，若非老式向前迭代器 (LegacyForwardIterator) ，则 `T` 可移动插入 (MoveInsertable) | `[i,j)` 中的每个迭代器被解引用一次
a.assign(il) | `void` | a.assign(il.begin(),il.end()) |  |
a.assign(n,t) | `void` | 用 `t` 的 `n` 个副本替换 `a` 中的元素 | `T` 可复制插入 (CopyInsertable) 并可复制赋值 (CopyAssignable) |
注
↑ std::array 支持从花括号初始化器列表复制，但不支持从 std::initializer_list 赋值

下列表达式必须合法，且对于所指名的顺序容器拥有所指定的效果：

表达式 | 返回类型 | 效果 | 前条件 | 容器
--- | --- | --- | --- | ---
a.front() | `reference` 对于 const a 为 `const_reference` | 等价于 *a.begin() |  | （全部）
a.back() | `reference` 对于 const a 为 `const_reference` | 等价于 { auto tmp = a.end(); --tmp; return *tmp; } |  | std::basic_string std::array std::deque std::list std::vector
a.emplace_front(args) | `void` | 前附一个以 std::forward<Args>(args)... 构造的 `T` | `T` 从 `args` 可就位构造 (EmplaceConstructible) 到 `X` 中 | std::deque std::forward_list std::list
a.emplace_back(args) | `void` | 后附一个以 std::forward<Args>(args)... 构造的 `T` | `T` 从 `args` 可就位构造 (EmplaceConstructible) 到 `X` 中 (仅 std::vector) `T` 可移动插入 (MoveInsertable) 到 `X` 中 | std::deque std::list std::vector
a.push_front(t) | `void` | 前附 `t` 的一个副本 | `T` 可复制插入 (CopyInsertable) 到 `X` 中 | std::deque std::forward_list std::list
a.push_front(rv) | `void` | 前附 `rv` 的一个副本，可能用移动语义 | `T` 可移动插入 (MoveInsertable) 到 `X` 中 | std::deque std::forward_list std::list
a.push_back(t) | `void` | 后附 `t` 的一个副本 | `T` 可复制插入 (CopyInsertable) 到 `X` 中 | std::basic_string std::deque std::list std::vector
a.push_back(rv) | `void` | 后附 `rv` 的一个副本，可能用移动语义 | `T` 可移动插入 (MoveInsertable) 到 `X` 中 | std::basic_string std::deque 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::list std::vector
a[n] | `reference` 对于 const a 为 `const_reference` | 等价于 *(n + a.begin()) |  | std::basic_string std::array std::deque std::vector
a.at(n) | `reference` 对于 const a 为 `const_reference` | 等价于 *(n + a.begin())，但若 n>=size() 则抛出 out_of_range |  | std::basic_string std::array std::deque std::vector

另外，对于每个顺序容器，接收两个输入迭代器的构造函数模板和成员函数 `insert()`、`append()`、`assign()`、`replace()` 的模板重载，若相应的模板实参不满足老式输入迭代器 (LegacyInputIterator) ，则它们不参与重载决议。

### 标准库中的顺序容器

basic_string | 存储并操作字符序列 (类模板)
array (C++11) | 静态的连续数组 (类模板)
vector | 动态的连续数组 (类模板)
deque | 双端队列 (类模板)
forward_list (C++11 起) | 单链表 (类模板)
list | 双链表 (类模板)

#### 权衡/使用备注

std::array | 快速访问但元素数量固定
std::vector | 快速访问但大多情况在插入/删除低效
std::list std::forward_list | 在序列中部高效地插入/删除
std::deque | 在序列首尾高效地插入/删除