命名空间
变体
操作

C++ 命名要求: SequenceContainer

来自 cppreference.cn
< cpp‎ | named req
 
 
C++ 命名要求
 

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,使得 [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++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 的副本。
前提条件

TCopyInsertableC 中的。

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

TEmplaceConstructibleC 中,从 *i

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

TCopyInsertableC 中的。

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

TCopyInsertableC 中且 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 效果 [ij) 的副本替换 v 中的元素。
  • 使所有引用、指针和迭代器(引用 v 的元素)失效。
  • 范围 [ij) 中的每个迭代器都被解引用恰好一次。
前提条件
(自 C++11 起)
  • ij 不在 v 中。
v.assign_range(rg)
(自 C++23 起)
void 效果 rg 中每个元素的副本替换 v 中的元素。
  • 如果 std::assignable_from
        <T&, ranges::range_reference_t<R>>
    未建模,则程序是非良构的。
  • 使所有引用、指针和迭代器(引用 v 的元素)失效。
  • 范围 rg 中的每个迭代器都被解引用恰好一次。
前提条件
v.assign(il)
(自 C++11 起)
void 等价于 v.assign(il.begin(), il.end())
v.assign(n, t) void 效果 nt 的副本替换 v 中的元素。
前提条件

TCopyInsertableC 中且 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
效果 前置一个类型为 T 的对象,该对象使用 std::forward<Args>(args)... 构造。
返回值 v.front()
前提条件 TEmplaceConstructibleC 中,从 args
v.emplace_back(args)
(自 C++11 起)
void 容器 vector, inplace_vector, deque, list
效果 追加一个类型为 T 的对象,该对象使用 std::forward<Args>(args)... 构造。
返回值 v.back()
前提条件 TEmplaceConstructibleC 中,从 args
v.push_front(t) void 容器 deque, list, forward_list
效果 前置 t 的副本。
前提条件

TCopyInsertableC 中的。

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

TCopyInsertableC 中的。

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

此外,对于每个序列容器

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

[编辑] 标准库

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

存储和操作字符序列
(类模板) [编辑]
(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 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.erase(v.begin(), v.end()) 的行为未定义,如果 v 是一个空容器。
  2. 如果 v.end() 的类型是基本类型,则 --v.end() 是病态形式。 当 v 的类型是模板时,这是危险的,在这种情况下,这个错误可能很难被发现。
  3. 在 C++98 中,它们没有被记录为 SequenceContainers。