C++11 std::allocator_traits
模板用于查询Allocator
以确定propagate_on_copy_assignment
和propagate_on_move_assignment
是否true
。 这些值会影响容器类型必须实现复制和移动分配的方式。 如果std::allocator_traits<Allocator>::propagate_on_move_assignment == true
则容器移动分配操作员必须使用 RHS 容器对象中包含的分配器移动分配其内部分配器对象。
据推测,这样做的要点是,我们可以实现Allocator
类型,这些类型可以通知客户端容器move
或copy
操作是否应该要求我们在分配器中复制任何内部状态。
那么......为什么这些类型定义只适用于赋值。 为什么我们没有propagate_on_copy_construct
和propagate_on_move_construct
? 如果分配器具有某种内部状态,则客户端容器对象是否应该意识到这一点,以便它知道是否应该复制/移动分配器?
在作业中,有两个选择:
- 保留现有的分配器。
- 从 rhs 分配器复制/移动。
propagate_on_assign
特征控制赋值运算符的选择。
对于构造,选择 1(保留现有分配器(不是一个选项。 没有现有的分配器。 相反,您的选择是:
- 从无到有构建分配器。
- 从 rhs 分配器复制/移动。
- 从其他来源复制/移动。
可以考虑选择一种:默认构造一个分配器。 选择 3 非常模糊,但不同的分配器方案可能是不可预测的,最好给分配器设计者尽可能多的灵活性:可能做一些委员会从未预料到的事情。
为了满足所有三个选择,至少对于容器复制构造函数,设计了一个新的allocator_traits"开关":
Alloc select_on_container_copy_construction(const Alloc& rhs);
allocator_traits
将返回rhs. select_on_container_copy_construction()
如果该表达式格式正确。 否则它将返回rhs
. 容器复制构造函数在复制构造过程中构造 lhs 分配器时需要使用allocator_traits<A>:: select_on_container_copy_construction(a)
。
对于只想在复制构造期间复制分配器的分配器设计人员(选择 2(,他们不必执行任何操作。
想要在容器复制构造上构造 lhs 分配器默认值的分配器设计器只需要为其分配器编写以下成员函数:
Alloc select_on_container_copy_construction() const {return Alloc{};}
如果他们为选择 3 想到了一些聪明的东西,他们可能会使用与选择 1 相同的钩子来实现它。
因此,对于副本构造,不需要propagate_on
特征,因为select_on_container_copy_construction
已经涵盖了所有基础。
有关移动结构,请参阅 N12 第 2982 页的底部:
请注意,没有
select_on_container_move_construction()
功能。经过一番考虑,我们决定搬家 集装箱的施工操作必须在恒定时间内运行,并且 不抛出,根据问题 1166。
事实上,这篇论文以及它之前的论文(它引用的(是 C++11 分配器设计背后的基本原理的良好信息来源。 本文甚至引用了前一篇论文的allocator_propagate_on_copy_construction
,该论文后来演变为select_on_container_copy_construction()
。