13

在阅读有关复制和交换习语的内容后,我阅读(2)下的内容:

class_name & class_name :: operator= ( const class_name & )     (2)     

(2)不能使用复制和交换习语时复制赋值运算符的典型声明

我们什么时候应该避免使用复制和交换习语?

什么时候完全“不能使用”?

是否存在复制和交换和零规则都不适用的现实案例?

我确实找到了这个问题,但它太具体了,并且没有包含任何关于如何识别此类案例的指南。

4

2 回答 2

7

我们什么时候应该避免使用复制和交换习语?

当您可以证明 naïve copy 比swap.

您可以识别没有拥有对象的成员指针(既不是智能指针也不是原始指针)的情况,并且对于所有成员对象都是如此。

什么时候完全“不能使用”?

当类型不可交换时,不能使用复制和交换。

要可交换,该类型必须是可移动构造和可移动分配的,或者您必须已定义swap成员函数或友元函数。

于 2015-11-16T12:19:48.827 回答
2

您描述的赋值运算符的潜在实现的链接描述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&)

表明它将在任何子类的实现者身上,以确保进行足够的检查以通过自分配测试。

于 2015-11-16T12:23:27.717 回答