C++ 具名要求:知分配器容器 (AllocatorAwareContainer)
来自cppreference.com
                    
                                        
                    
                    
                                                            
                    知分配器容器 (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()获得构造容器时所用的,或为最近的分配器替换操作所安装的分配器的一个副本。 
要求
凡例
 X
 | 
容器类型 | 
 T
 | 
元素类型 | 
 A
 | 
 T 的分配器
 | 
 a, b
 | 
 X 类型的对象(非 const 左值)
 | 
 t
 | 
 X 类型的对象(左值或 const 右值)
 | 
 rv
 | 
 X 类型的对象(非 const 右值)
 | 
 m
 | 
 A 类型的对象
 | 
 Q
 | 
分配器类型 | 
| 表达式 | 返回类型 | 前提/要求 | 后置/效应 | 复杂度 | 
|---|---|---|---|---|
| allocator_type | A | 
allocator_type::value_type 必须与 X::value_type 相同 | 编译时 | |
| get_allocator() | A | 
常数 | ||
| X u; | A 可默认构造 (DefaultConstructible)  | 
u.empty() == true && u.get_allocator() == A() | 常数 | |
| X u(m); | u.empty() == true && u.get_allocator() == m | 常数 | ||
| X u(t,m); | T 可复制插入 (CopyInsertable) 到 X
 | 
u == t && u.get_allocator() == m | 线性 | |
| X u(rv); | A 的移动构造函数必须不抛异常
 | 
u 拥有与 rv 构造前相同的元素和相等的分配器 | 
常数 | |
| X u(rv,m); | T 可移动插入 (MoveInsertable) 到 X
 | 
u 的元素与 rv 的相同或是其副本,且 u.get_allocator() == m
 | 
若 m == rv.get_allocator() 则为常数,否则为线性 | |
| a = t | X& | T 可复制插入 (CopyInsertable) 到 X 且可复制赋值 (CopyAssignable)   | 
a == t | 线性 | 
| a = rv | X& | 若分配器将不被移动赋值所替换(见上文),则 T 可移动插入 (MoveInsertable) 到 X 并可移动赋值 (MoveAssignable) 
 | 
a 的所有既存元素被移动赋值或销毁;若 a 与 rv 不指代同一对象则 a 等于 rv 赋值前所拥有的值 | 
线性 | 
| a.swap(b) | void | 交换 a 与 b 的内容 | 
常数 | 
注解
具分配器容器始终调用 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::allocator 无 construct 成员,而在构造元素时 std::construct_at(p, args) 得到调用 (C++20 起),但特化的分配器可以选择不同的定义。
标准库
所有标准库容器,除了 std::array,都是知分配器容器 (AllocatorAwareContainer) :
- std::basic_string
 - std::deque
 - std::forward_list
 - std::list
 - std::vector
 - std::map
 - std::multimap
 - std::set
 - std::multiset
 - std::unordered_map
 - std::unordered_multimap
 - std::unordered_set
 - std::unordered_multiset
 
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
| 缺陷报告 | 应用于 | 出版时的行为 | 正确行为 | 
|---|---|---|---|
| LWG 2839 | C++11 | 不允许标准容器的自移动赋值 | 容许但结果未指定 |