C++ 具名要求:知分配器容器 (AllocatorAwareContainer) (C++11 起)

来自cppreference.com
< cpp‎ | named req


 
 
C++ 具名要求
 

知分配器容器 (AllocatorAwareContainer) 容器 (Container) ,其保有一个分配器 (Allocator) 实例,并于其所有成员函数中用该实例来分配及解分配内存,并于这个内存中构造及销毁对象(这种对象可以是容器元素,节点,或对于无序容器为桶数组),但 std::basic_string 的特化不用分配器构造/析构它的元素(C++23 起)

下列规则适用于容器的构造:

  • 知分配器容器 (AllocatorAwareContainer) 的复制构造函数,通过在正在复制的容器的分配器上调用 std::allocator_traits<allocator_type>::select_on_container_copy_construction 获得自己的分配器实例。
  • 移动构造函数通过从属于旧容器的分配器进行移动构造,获得其自己的分配器实例。
  • 所有其他构造函数均接收一个 const allocator_type& 形参。

仅有的替换分配器的方式是进行移动赋值、复制赋值及交换:

  • 只有在 std::allocator_traits<allocator_type>::propagate_on_container_copy_assignment::valuetrue 时,复制赋值才会替换分配器。
  • 只有在 std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::valuetrue 时,移动赋值才会替换分配器 。
  • 只有在 std::allocator_traits<allocator_type>::propagate_on_container_swap::valuetrue 时,交换才会替换分配器。特别是它将通过对非成员函数 swap 的无限定的调用来交换分配器实例,见可交换 (Swappable)

注:如果 propagate_on_container_swapfalse,那么交换两个拥有不相等分配器的容器的行为未定义。

  • 访问器 get_allocator() 获得构造容器时所用的,或为最近的分配器替换操作所安装的分配器的一个副本。

要求

一个类型满足知分配器容器 (AllocatorAwareContainer) 的条件是,它满足容器 (Container) ,并且给定以下类型和值,它也满足下方表格列出的语义和复杂度要求:

类型定义
X知分配器容器 (AllocatorAwareContainer) 类型
TXvalue_type
AX 使用的分配器类型
定义
a, bX 类型非 const 左值
cconst X 类型左值
tX 左值或 const 右值
rvX 类型非 const 右值
mA 类型的值

类型

名字 类型 要求
typename X::allocator_type AX::allocator_type::value_typeX::value_type 相同。

语句

语句语义复杂度
X u;
X u = X();
前条件 A 可默认构造 (DefaultConstructible) 常数
后条件u.empty()u.get_allocator() == A() 都是 true
X u(m);后条件u.empty()u.get_allocator() == m 都是 true常数
X u(t, m);前条件T 可复制插入 (CopyInsertable) X 中。线性
后条件u == tu.get_allocator() == m 都是 true
X u(rv);后条件
  • u 包含的元素和 rv 在该构造前包含的元素相同。
  • u.get_allocator() 的值和 rv.get_allocator() 在该构造前的值相同。
常数
X u(rv, m);前条件T 可移动插入 (MoveInsertable) X 中。
  • m == rv.get_allocator()true时是常数。
  • 否则是线性。
后条件
  • u 包含的元素和 rv 在该构造前包含的元素相同,或者是那些元素的副本。
  • u.get_allocator() == mtrue

表达式

表达式类型语义 复杂度 
c.get_allocator()A没有直接语义要求。常数
a = tX&前条件 T 可复制插入 (CopyInsertable) X 中,并且可复制赋值 (CopyAssignable) 线性
后条件a == ttrue
a = rvX&前条件如果分配器不会被移动赋值替换(见上文),那么 T 可移动插入 (MoveInsertable) X 中,并且可移动赋值 (MoveAssignable) 线性
效果a 先前的所有元素都会被移动赋值或销毁。
后条件如果 arv 不指代统一对象,那么 a 的值和 rv 在该构造前的值相等。
a.swap(b)void 效果交换 ab常数

注解

知分配器容器 (AllocatorAwareContainer) 始终调用 std::allocator_traits<A>::construct(m, p, args)p 中用 args 来构造一个 A 类型的对象,其中 m == get_allocator()std::allocator 中默认的 construct 调用 ::new((void*)p) T(args)(C++20 前)std::allocatorconstruct 成员,而在构造元素时 std::construct_at(p, args) 得到调用(C++20 起),但特化的分配器可以选择不同的定义。

标准库

所有标准库的字符串类型和容器(除了 std::arraystd::inplace_vector)都是知分配器容器 (AllocatorAwareContainer)

存储并操作字符序列
(类模板)
双端队列
(类模板)
(C++11 起)
单向链表
(类模板)
双向链表
(类模板)
动态的连续数组
(类模板)
键值对的集合,按照键排序,键是唯一的
(类模板)
键值对的集合,按照键排序
(类模板)
唯一键的集合,按照键排序
(类模板)
键的集合,按照键排序
(类模板)
(C++11 起)
键值对的集合,按照键生成散列,键是唯一的
(类模板)
键值对的集合,按照键生成散列
(类模板)
(C++11 起)
唯一键的集合,按照键生成散列
(类模板)
键的集合,按照键生成散列
(类模板)

缺陷报告

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

缺陷报告应用于出版时的行为正确行为
LWG 2839C++11不允许标准容器的自移动赋值容许但结果未指定