在阅读了有关复制和交换习语的内容后,我阅读了(2)下的内容:
class_name & class_name :: operator= ( const class_name & ) (2)
(2)不能使用复制和交换习语时复制赋值运算符的典型声明
我们什么时候应该避免使用复制和交换习语?
什么时候完全“不能使用”?
是否存在复制和交换和零规则都不适用的现实案例?
我确实找到了这个问题,但它太具体了,并且没有包含任何关于如何识别此类案例的指南。
我们什么时候应该避免使用复制和交换习语?
当您可以证明 naïve copy 比swap
.
您可以识别没有拥有对象的成员指针(既不是智能指针也不是原始指针)的情况,并且对于所有成员对象都是如此。
什么时候完全“不能使用”?
当类型不可交换时,不能使用复制和交换。
要可交换,该类型必须是可移动构造和可移动分配的,或者您必须已定义swap
成员函数或友元函数。
您描述的赋值运算符的潜在实现的链接描述class_name& class_name::operator=(class_name)
为:
可以使用复制和交换习语时复制赋值运算符的典型声明
并且class_name& class_name::operator=(const class_name&)
作为:
无法使用复制和交换习语时复制赋值运算符的典型声明
基本上,我们总是希望尽可能使用复制和交换,正如对您的链接问题的出色回答中所述,因为它将通过自我分配测试。
所以现在的问题是为什么http://www.cppreference.com上提到的约定?
假设我正在为一个虚拟类实现一个复制构造函数,我想向任何将继承的人明确表示他们应该使用复制和交换习语。我该怎么做?我可以通过在初次通话中为他们制作副本来帮助他们:
class_name& class_name::operator=(class_name)
这是按值复制的,因此任何子类的实现者都会看到我已经为他们制作了副本,所以他们需要做的就是交换。
现在,如果我有一个class_name
包含无法复制构造的成员怎么办,例如,如果我的类有一个不能复制构造的成员怎么办unique_ptr
。我可以通过不向赋值运算符复制值参数来表明这一点,例如:
class_name& class_name::operator(const class_name&)
表明它将在任何子类的实现者身上,以确保进行足够的检查以通过自分配测试。