跳到主要内容

C++ 命名要求: SequenceContainer

SequenceContainer 是一种将相同类型对象以线性排列方式存储的Container

要求

如果类型 X 满足 SequenceContainer,则:

给定

  • T,X 的元素类型
  • A,X 的分配器类型:如果存在,则为 X::allocator_type,否则为 std::allocator<T>
  • a,类型为 X 的右值表达式
  • p,指向 a 的有效 const 迭代器
  • q,指向 a 的有效可解引用 const 迭代器
  • q1q2,指向 a 的两个 const 迭代器,使得 [q1, q2) 是一个有效范围
  • ijLegacyInputIterators,使得 [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)
构造持有 nt 副本的序列容器TCopyInsertableXstd::distance(begin(), end())
    == n
X(i, j)
X a(i, j)
构造序列容器,其元素与范围 [i, j) 逐个相等T 可从 i EmplaceConstructibleX 中(仅适用于 std::vector)。如果迭代器不是 LegacyForwardIterator,则 T 必须是 CopyInsertablestd::distance(begin(), end())
    == std::distance(i, j)
X(il)X(il.begin(), il.end())
a = ilX&il 表示的范围赋值给 a[1]TCopyInsertable 且可 CopyAssignablea 的现有元素被销毁或赋值
a.emplace(p, args)iteratorp 之前插入一个类型为 T 的对象,该对象使用 std::forward<Args>(args) 构造TEmplaceConstructible
(对于 std::vectorstd::dequeTMoveAssignable 且可 MoveInsertable
返回的迭代器指向从 args 构造到 a 中的元素
a.insert(p, t)iteratorp 之前插入 t 的副本TCopyInsertable
(对于 std::vectorstd::dequeTCopyAssignable 或可 MoveAssignable
返回的迭代器指向插入到 a 中的 t 的副本
a.insert(p, rv)iteratorp 之前插入 rv 的副本,可能使用移动语义TMoveInsertable
(对于 std::vectorstd::dequeTMoveAssignable
返回的迭代器指向插入到 a 中的 rv 的副本
a.insert(p, n, t)iteratorp 之前插入 nt 的副本TCopyInsertable 且可 CopyAssignable返回的迭代器指向插入到 a 中的第一个元素的副本,如果 n == 0 则为 p
a.insert(p, i, j)iteratorp 之前插入 [i, j) 中元素的副本TEmplaceConstructibleij 不在 a
(仅适用于 std::vector)如果迭代器不是 LegacyForwardIterator,则 T 必须是可 MoveInsertable 且可 MoveAssignable
[i, j) 中的每个迭代器都被解引用一次。返回的迭代器指向插入到 a 中的第一个元素的副本,如果 i == j 则为 p
a.insert(p, il)iteratora.insert(p,
    il.begin(),
    il.end())
返回的迭代器指向插入到 a 中的第一个元素的副本,如果 il 为空则为 p
a.erase(q)iterator擦除 q 所指向的元素(std::deque, std::vector)
TMoveAssignable
返回的迭代器指向擦除前紧随 q 的元素,如果不存在此类元素,则为 a.end()
a.erase(q1, q2)iterator擦除 [q1, q2) 中的元素(std::deque, std::vector)
TMoveAssignable
返回的迭代器指向擦除前由 q2 所指向的元素,如果不存在此类元素,则为 a.end()
a.clear()void销毁 a 中的所有元素所有引用、指针和迭代器(包括 end 迭代器)均无效。a.empty() == true
a.assign(i, j)void[i, j) 的副本替换 a 中的元素TEmplaceConstructiblei, j 不在 a
(std::vector) 如果不是 LegacyForwardIteratorTMoveInsertable
[i, j) 中的每个迭代器都被解引用一次
a.assign(il)voida.assign(il.begin(),
    il.end())
a.assign(n, t)voidnt 的副本替换 a 中的元素TCopyInsertable 且可 CopyAssignable

备注

1 std::array 支持从大括号初始化列表赋值,但不支持从 std::initializer_list 赋值

可选操作

以下表达式对于指定序列容器必须有效并具有其指定的效果,所有操作均具有均摊常数时间

表达式返回类型效果前置条件容器
a.front()引用
对于 const a 为 const_reference
等同于 *a.begin()(所有)
a.back()引用
对于 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)... 构造的 TT 可从 args EmplaceConstructibleXstd::deque
std::forward_list
std::list
a.emplace_back(args)void在后面添加一个用 std::forward<Args>(args)... 构造的 TT 可从 args EmplaceConstructibleX 中(仅限 std::vector)T 可 MoveInsertable 到 Xstd::deque
std::list
std::vector
a.push_front(t)void在前面添加 t 的副本TCopyInsertableXstd::deque
std::forward_list
std::list
a.push_front(rv)void在前面添加 rv 的副本,可能使用移动语义TMoveInsertableXstd::deque
std::forward_list
std::list
a.push_back(t)void在后面添加 t 的副本TCopyInsertableXstd::basic_string
std::deque
std::list
std::vector
a.push_back(rv)void在后面添加 rv 的副本,可能使用移动语义TMoveInsertableXstd::basic_string
std::deque
std::list
std::vector
a.pop_front()void销毁第一个元素。a.empty() == falsestd::deque
std::forward_list
std::list
a.pop_back()void销毁最后一个元素a.empty() == falsestd::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_rangestd::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 139C++98可选操作不需要为指定容器实现以均摊时间要求
LWG 149C++98a.insert(p, t) 返回迭代器,而 a.insert(p, n, t)a.insert(p, n, t) 返回 void它们都返回迭代器
LWG 151C++98q1 是可解引用的[1]它可以是不可解引用的
LWG 355C++98调用 a.back()a.pop_back() 会执行 --a.end(),这是危险的[2]改为递减 a.end() 的副本
LWG 589C++98ij 引用的元素可能无法转换为 value_type它们可隐式转换为 value_type

1 这是一个缺陷,因为它使得当 a 是空容器时,a.erase(a.begin(), a.end()) 的行为未定义。
2 如果 a.end() 的类型是基本类型,则 --a.end() 是格式错误的。当 a 的类型是模板化的,在这种情况下这个错误可能很难被发现。

C++ 命名要求: SequenceContainer

SequenceContainer 是一种将相同类型对象以线性排列方式存储的Container

要求

如果类型 X 满足 SequenceContainer,则:

给定

  • T,X 的元素类型
  • A,X 的分配器类型:如果存在,则为 X::allocator_type,否则为 std::allocator<T>
  • a,类型为 X 的右值表达式
  • p,指向 a 的有效 const 迭代器
  • q,指向 a 的有效可解引用 const 迭代器
  • q1q2,指向 a 的两个 const 迭代器,使得 [q1, q2) 是一个有效范围
  • ijLegacyInputIterators,使得 [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)
构造持有 nt 副本的序列容器TCopyInsertableXstd::distance(begin(), end())
    == n
X(i, j)
X a(i, j)
构造序列容器,其元素与范围 [i, j) 逐个相等T 可从 i EmplaceConstructibleX 中(仅适用于 std::vector)。如果迭代器不是 LegacyForwardIterator,则 T 必须是 CopyInsertablestd::distance(begin(), end())
    == std::distance(i, j)
X(il)X(il.begin(), il.end())
a = ilX&il 表示的范围赋值给 a[1]TCopyInsertable 且可 CopyAssignablea 的现有元素被销毁或赋值
a.emplace(p, args)iteratorp 之前插入一个类型为 T 的对象,该对象使用 std::forward<Args>(args) 构造TEmplaceConstructible
(对于 std::vectorstd::dequeTMoveAssignable 且可 MoveInsertable
返回的迭代器指向从 args 构造到 a 中的元素
a.insert(p, t)iteratorp 之前插入 t 的副本TCopyInsertable
(对于 std::vectorstd::dequeTCopyAssignable 或可 MoveAssignable
返回的迭代器指向插入到 a 中的 t 的副本
a.insert(p, rv)iteratorp 之前插入 rv 的副本,可能使用移动语义TMoveInsertable
(对于 std::vectorstd::dequeTMoveAssignable
返回的迭代器指向插入到 a 中的 rv 的副本
a.insert(p, n, t)iteratorp 之前插入 nt 的副本TCopyInsertable 且可 CopyAssignable返回的迭代器指向插入到 a 中的第一个元素的副本,如果 n == 0 则为 p
a.insert(p, i, j)iteratorp 之前插入 [i, j) 中元素的副本TEmplaceConstructibleij 不在 a
(仅适用于 std::vector)如果迭代器不是 LegacyForwardIterator,则 T 必须是可 MoveInsertable 且可 MoveAssignable
[i, j) 中的每个迭代器都被解引用一次。返回的迭代器指向插入到 a 中的第一个元素的副本,如果 i == j 则为 p
a.insert(p, il)iteratora.insert(p,
    il.begin(),
    il.end())
返回的迭代器指向插入到 a 中的第一个元素的副本,如果 il 为空则为 p
a.erase(q)iterator擦除 q 所指向的元素(std::deque, std::vector)
TMoveAssignable
返回的迭代器指向擦除前紧随 q 的元素,如果不存在此类元素,则为 a.end()
a.erase(q1, q2)iterator擦除 [q1, q2) 中的元素(std::deque, std::vector)
TMoveAssignable
返回的迭代器指向擦除前由 q2 所指向的元素,如果不存在此类元素,则为 a.end()
a.clear()void销毁 a 中的所有元素所有引用、指针和迭代器(包括 end 迭代器)均无效。a.empty() == true
a.assign(i, j)void[i, j) 的副本替换 a 中的元素TEmplaceConstructiblei, j 不在 a
(std::vector) 如果不是 LegacyForwardIteratorTMoveInsertable
[i, j) 中的每个迭代器都被解引用一次
a.assign(il)voida.assign(il.begin(),
    il.end())
a.assign(n, t)voidnt 的副本替换 a 中的元素TCopyInsertable 且可 CopyAssignable

备注

1 std::array 支持从大括号初始化列表赋值,但不支持从 std::initializer_list 赋值

可选操作

以下表达式对于指定序列容器必须有效并具有其指定的效果,所有操作均具有均摊常数时间

表达式返回类型效果前置条件容器
a.front()引用
对于 const a 为 const_reference
等同于 *a.begin()(所有)
a.back()引用
对于 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)... 构造的 TT 可从 args EmplaceConstructibleXstd::deque
std::forward_list
std::list
a.emplace_back(args)void在后面添加一个用 std::forward<Args>(args)... 构造的 TT 可从 args EmplaceConstructibleX 中(仅限 std::vector)T 可 MoveInsertable 到 Xstd::deque
std::list
std::vector
a.push_front(t)void在前面添加 t 的副本TCopyInsertableXstd::deque
std::forward_list
std::list
a.push_front(rv)void在前面添加 rv 的副本,可能使用移动语义TMoveInsertableXstd::deque
std::forward_list
std::list
a.push_back(t)void在后面添加 t 的副本TCopyInsertableXstd::basic_string
std::deque
std::list
std::vector
a.push_back(rv)void在后面添加 rv 的副本,可能使用移动语义TMoveInsertableXstd::basic_string
std::deque
std::list
std::vector
a.pop_front()void销毁第一个元素。a.empty() == falsestd::deque
std::forward_list
std::list
a.pop_back()void销毁最后一个元素a.empty() == falsestd::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_rangestd::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 139C++98可选操作不需要为指定容器实现以均摊时间要求
LWG 149C++98a.insert(p, t) 返回迭代器,而 a.insert(p, n, t)a.insert(p, n, t) 返回 void它们都返回迭代器
LWG 151C++98q1 是可解引用的[1]它可以是不可解引用的
LWG 355C++98调用 a.back()a.pop_back() 会执行 --a.end(),这是危险的[2]改为递减 a.end() 的副本
LWG 589C++98ij 引用的元素可能无法转换为 value_type它们可隐式转换为 value_type

1 这是一个缺陷,因为它使得当 a 是空容器时,a.erase(a.begin(), a.end()) 的行为未定义。
2 如果 a.end() 的类型是基本类型,则 --a.end() 是格式错误的。当 a 的类型是模板化的,在这种情况下这个错误可能很难被发现。