跳到主要内容

C++ 命名要求: AllocatorAwareContainer (自 C++11 起)

AllocatorAwareContainer 是一种Container,它持有一个Allocator实例,并在其所有成员函数中使用该实例来分配和释放内存,以及在该内存中构造和销毁对象(这些对象可以是容器元素、节点,或者对于无序容器,是桶数组),但std::basic_string特化不使用分配器来构造/销毁其元素 (自 C++23 起)

以下规则适用于容器构造

  • AllocatorAwareContainers 的拷贝构造函数通过在被拷贝容器的分配器上调用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_swap 为false,则交换两个分配器不相等的容器是未定义行为。

  • 访问器 get_allocator() 获取用于构造容器或最近的分配器替换操作安装的分配器的副本。

要求

图例

X - 容器类型
T - 元素类型
A - T 的分配器
a, b - X 类型的对象(非 const 左值)
t - X 类型的对象(左值或 const 右值)
rv - X 类型的对象(非 const 右值)
m - A 类型的对象

表达式返回类型前/要求后/效果复杂度
allocator_typeAallocator_type::value_type 必须与 X::value_type 相同编译时
get_allocator()A常量
X u;ADefaultConstructibleu.empty() == true && u.get_allocator() == A()常量
X u(m);u.empty() == true && u.get_allocator() == m常量
X u(t,m);TCopyInsertableXu == t && u.get_allocator() == m线性
X u(rv);A 的移动构造函数不得抛出异常u 具有与构造前 rv 相同的元素和相等的分配器常量
X u(rv,m);TMoveInsertableXu 的元素与 rv 的元素相同或为副本,并且 u.get_allocator() == m如果 m == rv.get_allocator() 则为常数,否则为线性
a = tX&TCopyInsertableX中且CopyAssignablea == t线性
a = rvX&如果分配器不会被移动赋值替换(见上文),则TMoveInsertable到X中且MoveAssignablea 的所有现有元素要么被移动赋值,要么被销毁;如果 arv 不指向同一个对象,则 a 等于赋值前 rv 的值。线性
a.swap(b)void交换 ab 的内容常量

备注

Allocator-aware 容器总是调用 std::allocator_traits<A>::construct(m, p, args) 来在 p 处使用 args 构造一个 T 类型的对象,其中 m == get_allocator()std::allocator 中的默认构造调用 ::new((void*)p) T(args)  (直到 C++20) std::allocator 没有 construct 成员,并且在构造元素时调用 std::construct_at(p, args)  (自 C++20 起),但专门的分配器可以选择不同的定义

标准库

缺陷报告

以下改变行为的缺陷报告已追溯应用于先前发布的 C++ 标准。

DR应用于发布时的行为正确行为
LWG 2839C++11标准容器的自移动赋值不被允许允许,但结果未指定

C++ 命名要求: AllocatorAwareContainer (自 C++11 起)

AllocatorAwareContainer 是一种Container,它持有一个Allocator实例,并在其所有成员函数中使用该实例来分配和释放内存,以及在该内存中构造和销毁对象(这些对象可以是容器元素、节点,或者对于无序容器,是桶数组),但std::basic_string特化不使用分配器来构造/销毁其元素 (自 C++23 起)

以下规则适用于容器构造

  • AllocatorAwareContainers 的拷贝构造函数通过在被拷贝容器的分配器上调用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_swap 为false,则交换两个分配器不相等的容器是未定义行为。

  • 访问器 get_allocator() 获取用于构造容器或最近的分配器替换操作安装的分配器的副本。

要求

图例

X - 容器类型
T - 元素类型
A - T 的分配器
a, b - X 类型的对象(非 const 左值)
t - X 类型的对象(左值或 const 右值)
rv - X 类型的对象(非 const 右值)
m - A 类型的对象

表达式返回类型前/要求后/效果复杂度
allocator_typeAallocator_type::value_type 必须与 X::value_type 相同编译时
get_allocator()A常量
X u;ADefaultConstructibleu.empty() == true && u.get_allocator() == A()常量
X u(m);u.empty() == true && u.get_allocator() == m常量
X u(t,m);TCopyInsertableXu == t && u.get_allocator() == m线性
X u(rv);A 的移动构造函数不得抛出异常u 具有与构造前 rv 相同的元素和相等的分配器常量
X u(rv,m);TMoveInsertableXu 的元素与 rv 的元素相同或为副本,并且 u.get_allocator() == m如果 m == rv.get_allocator() 则为常数,否则为线性
a = tX&TCopyInsertableX中且CopyAssignablea == t线性
a = rvX&如果分配器不会被移动赋值替换(见上文),则TMoveInsertable到X中且MoveAssignablea 的所有现有元素要么被移动赋值,要么被销毁;如果 arv 不指向同一个对象,则 a 等于赋值前 rv 的值。线性
a.swap(b)void交换 ab 的内容常量

备注

Allocator-aware 容器总是调用 std::allocator_traits<A>::construct(m, p, args) 来在 p 处使用 args 构造一个 T 类型的对象,其中 m == get_allocator()std::allocator 中的默认构造调用 ::new((void*)p) T(args)  (直到 C++20) std::allocator 没有 construct 成员,并且在构造元素时调用 std::construct_at(p, args)  (自 C++20 起),但专门的分配器可以选择不同的定义

标准库

缺陷报告

以下改变行为的缺陷报告已追溯应用于先前发布的 C++ 标准。

DR应用于发布时的行为正确行为
LWG 2839C++11标准容器的自移动赋值不被允许允许,但结果未指定