C++ 命名要求: AllocatorAwareContainer (自 C++11 起)
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::value 为 true 时,复制赋值才会替换分配器。
- 只有当 std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value 为 true 时,移动赋值才会替换分配器。
- 只有当 std::allocator_traits<allocator_type>::propagate_on_container_swap::value 为 true 时,交换才会替换分配器。具体而言,它将通过对非成员函数 swap 的非限定调用来交换分配器实例,参见 Swappable。
注意:如果 propagate_on_container_swap
为 false,则交换两个具有不等分配器的容器的行为是未定义的。
- 访问器
get_allocator()
获取用于构造容器或通过最近的分配器替换操作安装的分配器的副本。
目录 |
[编辑] 要求
如果一个类型满足 Container,并且在给定以下类型和值的情况下,满足下表中的语义和复杂度要求,则该类型满足 AllocatorAwareContainer
类型 | 定义 |
X
|
一个 AllocatorAwareContainer 类型 |
T
|
X 的 value_type |
A
|
X 使用的分配器类型 |
值 | 定义 |
a, b | 类型 X 的非常量左值 |
c | 类型 const X 的左值 |
t | 类型 X 的左值或常量右值 |
rv | 类型 X 的非常量右值 |
m | 类型 A 的值 |
[编辑] 类型
名称 | 类型 | 要求 |
---|---|---|
typename X::allocator_type | A
|
X::allocator_type::value_type 和 X::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 == t 和 u.get_allocator() == m 都为 true。 | ||
X u(rv); | 后置条件 |
|
常量 |
X u(rv, m); | 前提条件 | T 可 MoveInsertable 到 X 中。 |
|
后置条件 |
|
[编辑] 表达式
表达式 | 类型 | 语义 | 复杂度 | |
---|---|---|---|---|
c.get_allocator() | A
|
无直接语义要求。 | 常量 | |
a = t | X&
|
前提条件 | T 可 CopyInsertable 到 X 中,且 CopyAssignable。 |
线性 |
后置条件 | a == t 为 true。 | |||
a = rv | X&
|
前提条件 | 如果分配器将不会被移动赋值替换(参见上方),则 T 可 MoveInsertable 到 X 中,且 MoveAssignable。 |
线性 |
效果 | a 的所有现有元素要么被移动赋值,要么被销毁。 | |||
后置条件 | 如果 a 和 rv 不引用同一对象,则 a 等于赋值之前 rv 拥有的值。 | |||
a.swap(b) | void | 效果 | 交换 a 和 b 的内容。 | 常量 |
[编辑] 注释
AllocatorAwareContainer 始终调用 std::allocator_traits<A>::construct(m, p, args) 以使用 args 在 p 处构造类型为 T
的对象,其中 m == get_allocator()。 std::allocator 中的默认 construct
调用 ::new((void*)p) T(args)(直到 C++20)std::allocator 没有 construct
成员,并且在构造元素时调用 std::construct_at(p, args)(自 C++20 起),但专门的分配器可以选择不同的定义。
[编辑] 标准库
所有标准库字符串类型和容器(除了 std::array 和 std::inplace_vector)都是 AllocatorAwareContainer
存储和操作字符序列 (类模板) | |
双端队列 (类模板) | |
(C++11) |
单链表 (类模板) |
双链表 (类模板) | |
可调整大小的连续数组 (类模板) | |
键值对集合,按键排序,键是唯一的 (类模板) | |
键值对集合,按键排序 (类模板) | |
唯一键的集合,按键排序 (类模板) | |
键的集合,按键排序 (类模板) | |
(C++11) |
键值对集合,按键哈希,键是唯一的 (类模板) |
(C++11) |
键值对集合,按键哈希 (类模板) |
(C++11) |
唯一键的集合,按键哈希 (类模板) |
(C++11) |
键的集合,按键哈希 (类模板) |
[编辑] 缺陷报告
以下行为变更缺陷报告被追溯应用于先前发布的 C++ 标准。
DR | 应用于 | 已发布行为 | 正确行为 |
---|---|---|---|
LWG 2839 | C++11 | 标准容器的自移动赋值是不允许的 | 允许但结果未指定 |