命名空间
变体
操作

C++ 命名要求: SequenceContainer

来自 cppreference.cn
 
 
C++ 命名要求
基本
类型属性
全库范围




Container(容器)
SequenceContainer(序列容器)
容器元素
迭代器 (Iterator)
流 I/O
格式化器
(C++20)
随机数
并发
(C++11)
Ranges
多维视图
其他

 

SequenceContainer 是一种 Container,它以线性排列存储相同类型的对象。

目录

[编辑] 要求

给定以下类型和值:

类型 定义
C 序列容器类
T C 的元素类型
A C 的分配器类型
  • 如果存在,则为 C::allocator_type
  • 否则为 std::allocator<T>
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,使得 [ij) 是一个 有效范围,并且迭代器引用隐式可转换为 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 迭代器,使得 [q1q2) 是一个有效范围
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); 效果 构造一个序列容器,其中包含 nt 的副本。
前置条件

T 可以 CopyInsertableC 中。

(C++11 起)
后置条件  std::distance(c.begin(), c.end())n
C c(i, j); 效果 构造一个序列容器,其元素与范围 [ij) 逐元素相等。
  • 范围 [ij) 中的每个迭代器被解引用一次。
前置条件

T 可以从 *i EmplaceConstructibleC 中。

(C++11 起)
后置条件 std::distance(c.begin(), c.end()) 等于 std::distance(i, j)
表达式  类型  语义
C(std::from_range, rg)
(C++23 起)
C 效果 构造一个序列容器,其元素与范围 rg 逐元素相等。
  • 范围 rg 中的每个迭代器被解引用一次。
前置条件 T 可以从 *ranges::begin(rg) EmplaceConstructibleX 中。
后置条件 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 可以 CopyInsertableC 中,并且可以 CopyAssignable
后置条件 v 的现有元素被销毁或赋值。
v.emplace(p, args)
(C++11 起)
Iter  效果 p 之前插入一个用 std::forward<Args>(args)... 构造的 T 类型对象。
返回值 指向从 args 构造到 v 中的新元素的迭代器。
前置条件 T 可以从 args EmplaceConstructibleC 中。
v.insert(p, t) Iter 效果 p 之前插入 t 的一个副本。
返回值 指向插入到 v 中的 t 副本的迭代器。
前置条件

T 可以 CopyInsertableC 中。

(C++11 起)
v.insert(p, rv)
(C++11 起)
Iter 效果 p 之前插入 rv 的一个副本,可能使用移动语义。
返回值 指向插入到 v 中的 rv 副本的迭代器。
前置条件 T 可以 MoveInsertableC 中。
v.insert(p, n, t) Iter 效果 p 之前插入 nt 的副本。
返回值 指向插入到 v 中的第一个元素副本的迭代器,如果 n0,则为 p
前置条件

T 可以 CopyInsertableC 中,并且可以 CopyAssignable

(C++11 起)
v.insert(p, i, j) Iter 效果 p 之前插入范围 [ij) 中元素的副本。
  • 范围 [ij) 中的每个迭代器被解引用一次。
返回值 指向插入到 v 中的第一个元素副本的迭代器,如果 i == jtrue,则为 p
前置条件
(C++11 起)
  • ij 不在 v 中。
v.insert_range(p, rg)
(C++23 起)
Iter 效果 p 之前插入 rg 中元素的副本。
  • 范围 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 效果 擦除范围 [q1q2) 中的元素。
返回值 指向在任何元素被擦除之前由 q2 指向的元素的迭代器,如果不存在这样的元素,则为 v.end()
v.clear() void 效果 销毁 v 中的所有元素。
  • 使所有引用 v 元素的引用、指针和迭代器失效,并可能使 past-the-end 迭代器失效。
后置条件 v.empty()true
复杂度 线性。
v.assign(i, j) void 效果 v 中的元素替换为范围 [ij) 的副本。
  • 使所有引用 v 元素的引用、指针和迭代器失效。
  • 范围 [ij) 中的每个迭代器被解引用一次。
前置条件
(C++11 起)
  • ij 不在 v 中。
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 中的元素替换为 nt 的副本。
前置条件

T 可以 CopyInsertableC 中,并且可以 CopyAssignable

(C++11 起)
    额外操作[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 EmplaceConstructibleC 中。
v.emplace_back(args)
(C++11 起)
void 容器 vector, inplace_vector, deque, list
效果 追加一个用 std::forward<Args>(args)... 构造的 T 类型对象。
返回值 v.back()
前置条件 T 可以从 args EmplaceConstructibleC 中。
v.push_front(t) void 容器 deque, list, forward_list
效果 预先添加 t 的一个副本。
前置条件

T 可以 CopyInsertableC 中。

(C++11 起)
v.push_front(rv)
(C++11 起)
void 容器 deque, list, forward_list
效果 预先添加 rv 的一个副本,可能使用移动语义。
前置条件 T 可以 MoveInsertableC 中。
v.prepend_range(rg)
(C++23 起)
void 容器 deque, list, forward_list
效果 v.begin() 之前[6] 插入 rg 中元素的副本。
  • 范围 rg 中的每个迭代器被解引用一次。
前置条件 T 可以从 *ranges::begin(rg) EmplaceConstructibleC 中。
v.push_back(t) void 容器 basic_string, vector, inplace_vector, deque, list
效果 追加 t 的一个副本。
前置条件

T 可以 CopyInsertableC 中。

(C++11 起)
v.push_back(rv)
(C++11 起)
void 容器 basic_string, vector, inplace_vector, deque, list
效果 追加 rv 的一个副本,可能使用移动语义。
前置条件 T 可以 MoveInsertableC 中。
v.append_range(rg)
(C++23 起)
void 容器 vector, inplace_vector, deque, list
效果 v.end() 之前[6] 插入 rg 中元素的副本。
  • 范围 rg 中的每个迭代器被解引用一次。
前置条件 T 可以从 *ranges::begin(rg) EmplaceConstructibleC 中。
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
注意
  1. 对于效果等同于某些其他操作的表达式,这些操作内部表达式的条件将继承到表中列出的条件之上。
  2. std::array 支持从 大括号括起来的初始化列表 赋值,但不支持从 std::initializer_list 赋值。
  3. 以下所有操作,除了 prepend_rangeappend_range(从 C++23 开始),都采用摊销常数时间。
  4. 在 C++98 中,tmp 被声明为 C::iterator 类型。
  5. 在 C++98 中,tmp 被声明为 C::const_iterator 类型。
  6. 6.0 6.1 插入顺序相对于 rg 中元素的顺序是非反转的。

此外,对于每个序列容器:

  • 接受两个输入迭代器的构造函数模板以及接受两个输入迭代器的 insertappendassignreplace 成员函数模板重载,如果相应的模板参数不满足 LegacyInputIterator,则不参与重载决议。
  • 如果为具有 LegacyInputIteratorAllocator 模板参数的推导指南推导出的类型不符合输入迭代器或分配器的条件,则该推导指南不参与重载决议。
(C++17 起)

[编辑] 标准库

以下标准库字符串类型和容器满足 SequenceContainer 的要求:

存储和操作字符序列
(类模板) [编辑]
(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 ij 引用的元素
可能无法转换为 C::value_type
它们被隐式地
转换为 C::value_type
LWG 2194 C++11 std::queuestd::priority_queue
std::stack 也曾是 SequenceContainers[3]
它们不是 SequenceContainers
LWG 2231 C++11 v.clear() 的复杂度要求
在 C++11 中被错误地省略了
复杂度重新确认为线性
LWG 3927 C++98 operator[] 没有隐式要求 添加了隐式要求
  1. 这是一个缺陷,因为它使得如果 v 是一个空容器,那么 v.erase(v.begin(), v.end()) 的行为是未定义的。
  2. 如果 v.end() 的类型是基本类型,那么 --v.end() 是不合法的。当 v 的类型是模板化的,在这种情况下,这个错误很难被发现,这很危险。
  3. 在 C++98 中,它们没有被记录为 SequenceContainer