C++ 命名要求: SequenceContainer
SequenceContainer 是一种将相同类型对象以线性排列方式存储的Container。
要求
如果类型 X 满足 SequenceContainer,则:
- 类型 X 满足Container,并且
给定
T
,X 的元素类型A
,X 的分配器类型:如果存在,则为X::allocator_type
,否则为std::allocator
<T>a
,类型为 X 的右值表达式p
,指向a
的有效 const 迭代器q
,指向a
的有效可解引用 const 迭代器q1
和q2
,指向 a 的两个 const 迭代器,使得[q1, q2)
是一个有效范围i
和j
,LegacyInputIterators,使得[i, j)
是一个有效范围,并且迭代器引用的元素可隐式转换为 value_typeil
,类型为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()) | |
X(i, j) X a(i, j) | 构造序列容器,其元素与范围 [i, j) 逐个相等 | T 可从 i EmplaceConstructible 到 X 中(仅适用于 std::vector)。如果迭代器不是 LegacyForwardIterator,则 T 必须是 CopyInsertable | std::distance(begin(), end()) | |
X(il) | X(il.begin(), il.end()) | |||
a = il | X& | 将 il 表示的范围赋值给 a [1] | T 可 CopyInsertable 且可 CopyAssignable | a 的现有元素被销毁或赋值 |
a.emplace(p, args) | iterator | 在 p 之前插入一个类型为 T 的对象,该对象使用 std::forward<Args>(args) 构造 | T 可 EmplaceConstructible (对于 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 | 在 p 之前插入 n 个 t 的副本 | T 可 CopyInsertable 且可 CopyAssignable | 返回的迭代器指向插入到 a 中的第一个元素的副本,如果 n == 0 则为 p |
a.insert(p, i, j) | iterator | 在 p 之前插入 [i, j) 中元素的副本 | 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, | 返回的迭代器指向插入到 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 中的所有元素 | 所有引用、指针和迭代器(包括 end 迭代器)均无效。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(), | ||
a.assign(n, t) | void | 用 n 个 t 的副本替换 a 中的元素 | T 可 CopyInsertable 且可 CopyAssignable |
备注
1 std::array 支持从大括号初始化列表赋值,但不支持从 std::initializer_list 赋值
可选操作
以下表达式对于指定序列容器必须有效并具有其指定的效果,所有操作均具有均摊常数时间
表达式 | 返回类型 | 效果 | 前置条件 | 容器 |
---|---|---|---|---|
a.front() | 引用 对于 const a 为 const_reference | 等同于 *a.begin() | (所有) | |
a.back() | 引用 对于 const a 为 const_reference | 等同于{ | 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] | 引用 对于 const a 为 const_reference | 等同于 *(n + a.begin()) | std::basic_string std::array std::deque std::vector | |
a.at(n) | 引用 对于 const a 为 const_reference | 等同于 *(n + a.begin()) ,但如果 n >= size() 则抛出 std::out_of_range | std::basic_string std::array std::deque std::vector |
此外,对于每个序列容器,接受两个输入迭代器的构造函数模板以及接受两个输入迭代器的 insert()
、append()
、assign()
、replace()
成员函数模板重载,如果相应的模板参数不满足 LegacyInputIterator,则不参与重载解析。
标准库中的序列容器
公共 | basic_string | 存储和操作字符序列 |
公共 | array(C++11) | 静态连续数组 |
公共 | 向量 | 动态连续数组 |
公共 | 双端队列 | 双端队列 |
公共 | forward_list(C++11) | 单向链表 |
公共 | list | 双向链表 |
权衡 / 使用注意事项
公共 | std::vector | 快速访问但插入/删除效率普遍较低 |
公共 | std::array | 快速访问但元素数量固定 |
公共 | std::list std::forward_list | 在序列中间高效插入/删除 |
公共 | std::deque | 在序列开头和结尾高效插入/删除 |
缺陷报告
以下改变行为的缺陷报告已追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 发布时的行为 | 正确行为 |
---|---|---|---|
LWG 139 | C++98 | 可选操作不需要为指定容器实现 | 以均摊时间要求 |
LWG 149 | C++98 | a.insert(p, t) 返回迭代器,而 a.insert(p, n, t) 和 a.insert(p, n, t) 返回 void | 它们都返回迭代器 |
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 |
1 这是一个缺陷,因为它使得当 a
是空容器时,a.erase(a.begin(), a.end())
的行为未定义。
2 如果 a.end()
的类型是基本类型,则 --a.end()
是格式错误的。当 a
的类型是模板化的,在这种情况下这个错误可能很难被发现。