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

来自cppreference.com
< cpp‎ | named req
 
 
C++ 具名要求
基础
类型属性
库所属
容器
SequenceContainer
容器元素
(C++11)

迭代器
流 I/O
格式化
(C++20)
随机数
(C++11)    
并发
(C++11)
(C++11)
范围
其他
(C++11)


 

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

要求

以下情况下,类型 X序列容器 (SequenceContainer)

给定

  • TX 的元素类型
  • AX 的分配器类型:在 X::allocator_type 存在时是该类型,否则是 std::allocator<T>
  • aX 类型的左值表达式
  • pa 中的有效常量迭代器
  • qa 中的有效可解引用常量迭代器
  • q1q2a 中的两个有效常量迭代器,并且 [q1q2) 是有效范围
  • ij,两个使得 [ij) 是有效范围,且各迭代器指代能隐式转换成 value_type 的对象的老式输入迭代器 (LegacyInputIterator)
  • ilstd::initializer_list<value_type> 类型的对象
  • nX::size_type 类型的值
  • tX::value_type 类型的左值或 const 右值
  • rv,是 X::value_type 类型的非 const 右值
  • Args,模板形参包
  • args,拥有模式 Args&& 的函数形参包

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

表达式 返回类型 效果 前条件 后条件
X(n, t)

X a(n, t)

构造保有 nt 的副本的容器 T 可复制插入 (CopyInsertable) X std::distance(begin(),end())

    == n

X(i, j)

X a(i, j)

构造与范围 [ij) 逐元素相等的顺序容器 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 插入 nt 的副本到 p 之前 T 可复制插入 (CopyInsertable) 可复制赋值 (CopyAssignable) 返回指向插入到 a 中的首元素的副本的迭代器,或当 n == 0 时返回 p
a.insert(p, i, j) iterator 插入 [ij) 中元素的副本到 p 之前 T 可就位构造 (EmplaceConstructible) ij 不在 a

(仅对 std::vector)如果迭代器不是老式向前迭代器 (LegacyForwardIterator) ,那么 T 必须可移动插入 (MoveInsertable) 可移动赋值 (MoveAssignable)

[ij) 中的每个迭代器被解引用一次。返回指向插入到 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 擦除 [q1q2) 中的元素 (std::deque, std::vector) T 可移动赋值 (MoveAssignable) 返回指向在任何擦除前 q2 曾指向的元素的迭代器,或在不存在此种元素时返回 a.end()
a.clear() void 销毁 a 中所有元素

所有引用、指针及迭代器均失效,包含尾迭代器。a.empty() == true

a.assign(i, j) void [ij) 的副本替换 a 中的元素 T 可就位构造 (EmplaceConstructible) ,且 ij 不在 a

(std::vector),如果不是老式向前迭代器 (LegacyForwardIterator) ,那么 T 可移动插入 (MoveInsertable)

[ij) 中的每个迭代器被解引用一次
a.assign(il) void a.assign(il.begin(),
         il.end())
a.assign(n, t) void tn 个副本替换 a 中的元素 T 可复制插入 (CopyInsertable) 可复制赋值 (CopyAssignable)
  1. std::array 支持从花括号初始化器列表赋值,但不支持从 std::initializer_list 赋值

可选操作

下列表达式必须合法,且对于所指名的顺序容器拥有所指定的效果,所有操作都会在均摊常数时间内完成:

表达式 返回类型 效果 前条件 容器
a.front() reference

对于 const aconst_reference

等价于 *a.begin() (全部)
a.back() reference

对于 const aconst_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 Targs 可就位构造 (EmplaceConstructible) X std::deque std::forward_list std::list
a.emplace_back(args) void 后附一个以 std::forward<Args>(args)... 构造的 T Targs 可就位构造 (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 aconst_reference

等价于 *(n + a.begin()) std::basic_string std::array std::deque std::vector
a.at(n) reference

对于 const aconst_reference

等价于 *(n + a.begin()),但在 n >= size() 时会抛出 std::out_of_range std::basic_string std::array std::deque std::vector

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

标准库中的顺序容器

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

权衡/使用备注

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

缺陷报告

下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。

缺陷报告 应用于 出版时的行为 正确行为
LWG 139 C++98 在指定的容器上也不需要实现可选操作 需要以均摊常数时间实现
LWG 149 C++98 a.insert(p, t) 返回 iterator,但

a.insert(p, n, t)a.insert(p, n, t) 返回 void

都返回 iterator
LWG 151 C++98 q1 可解引用[1] 它不需要可解引用
LWG 355 C++98 调用 a.back()a.pop_back() 会执行危险[2]的操作 --a.end() 改成自减 a.end() 的副本
LWG 589 C++98 ij 指代的对象不一定可转换到 value_type 这些对象可以隐式转换到 value_type
  1. 它是缺陷的原因是它会导致在空容器 a 上调用 a.erase(a.begin(), a.end()) 的行为未定义。
  2. 如果 a.end() 具有基础类型,那么 --a.end() 非良构。当 a 时模板化类型的时候这个操作就变成了危险操作,它会在 a 的类型从非基础类型变成基础类型的时候导致编译失败,并且难以排查。