Sil*_*ler 18 c++ allocator c++11
我试图了解如何正确编写AllocatorAware容器.
我的理解是propagate_on_container_move_assignmenttypedef表示Allocator当Container本身被移动分配时是否需要复制某种类型.
所以,既然我找不到任何这方面的例子,我自己的抨击就像下面这样:
给定容器类型Container,Allocator类型allocator_type和内部allocator_type数据成员m_alloc:
Container& operator = (Container&& other)
{
if (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
{
m_alloc = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
other.m_alloc
);
}
return *this;
}
Run Code Online (Sandbox Code Playgroud)
它是否正确?
此外,另一个混乱的来源是嵌套的typedef propagate_on_container_move/copy_assignment专门讨论赋值 ...但是构造函数呢?移动构造函数或AllocatorAware容器的复制构造函数是否还需要检查这些typedef?我认为这里的答案是肯定的 ......意思是,我还需要写:
Container(Container&& other)
{
if (std::allocator_traits<allocator_type>::propagate_on_container_move_assignment::value)
{
m_alloc = std::allocator_traits<allocator_type>::select_on_container_copy_construction(
other.m_alloc
);
}
}
Run Code Online (Sandbox Code Playgroud)
How*_*ant 25
我建议研究libc ++的<vector>标题.您将不得不处理std :: lib实现者需要使用的所有令人讨厌的下划线.但是libc ++有一个符合C++ 11的实现,用于检查.
移动赋值运算符
容器移动赋值运算符必须处理三种不同的可能性:
propagate_on_container_move_assignment 是真的.propagate_on_container_move_assignment 是假的,来自lhs和rhs的分配器相等.propagate_on_container_move_assignment 是错误的,来自lhs和rhs的分配器比较不等.如果可能,这三种情况之间的决定应该在编译时进行,而不是在运行时进行.具体来说,应该在编译时在集合{1}和{2,3}之间进行选择,因为propagate_on_container_move_assignment它是编译时常量.编译时常量的编译时分支通常使用标记调度来完成,而不是在显示时使用if语句.
在这些情况下都不应该select_on_container_copy_construction使用.该函数仅适用于容器复制构造函数.
在情况1中,lhs应首先使用lhs的分配器来释放已分配的所有内存.这必须首先完成,因为rhs分配器可能无法在以后释放此内存.然后lhs分配器从rhs分配器移动分配(就像任何其他移动分配一样).然后将内存所有权从rhs容器传输到lhs容器.如果容器的设计使得rhs容器不能处于无资源状态(设计不良),则可以通过rhs分配器的移动来为rhs容器分配新资源.
如果propagate_on_container_move_assignment为false,则必须在运行时在情况2和3之间进行选择,因为分配器比较是运行时操作.
在案例2中,您可以执行与案例1 相同的操作,但不要移动分配分配器.跳过这一步.
在案例3中,您无法将任何内存的所有权从rhs容器转移到lhs容器.你唯一能做的就是:
assign(make_move_iterator(rhs.begin()), make_move_iterator(rhs.end()));
Run Code Online (Sandbox Code Playgroud)
请注意,在情况1中,因为算法是在编译时选择的value_type,所以容器的内容不必是MoveAssignablenor MoveInsertable(MoveConstructible)来移动 - 分配容器.但在情况2中,value_type小号就必须MoveAssignable和MoveInsertable(MoveConstructible),即使他们从来都是,因为你在2和3之间在运行时进行选择.并且3需要这些操作value_type来做assign.
移动赋值运算符很容易成为容器实现的最复杂的特殊成员.其余的更容易:
移动构造函数
移动构造函数只是移动构造分配器并从rhs窃取资源.
复制构造函数
复制构造函数从中获取其分配器select_on_container_copy_construction(rhs.m_alloc),然后使用它为复制分配资源.
复制赋值运算符
复制赋值运算符必须首先检查是否propagate_on_container_copy_assignment为真.如果是,并且如果lhs和rhs分配器比较不相等,那么lhs必须首先释放所有内存,因为在分配器被分配后,它将无法再这样做.接下来,如果propagate_on_container_copy_assignment,复制分配分配器,否则不.然后复制元素:
assign(rhs.begin(), rhs.end());
Run Code Online (Sandbox Code Playgroud)