为什么析构函数会禁用隐式移动方法的生成?

RaG*_*__M 16 c++ destructor move c++11 rule-of-zero

我试着通过阅读这篇博客来了解零的规则.IMO,它说如果你声明自己的析构函数,那么不要忘记创建移动构造函数并将赋值移动为默认值.

示例:

class Widget {
public:
  ~Widget();         // temporary destructor
  ...                // no copy or move functions
};
Run Code Online (Sandbox Code Playgroud)

"添加析构函数会产生禁用生成移动函数的副作用,但由于Widget是可复制的,因此用于生成移动的所有代码现在都会生成副本.换句话说,向类中添加析构函数可能会导致 - 有效的动作可以用可能效率低下的副本无声地替换".

Scott Meyers的上述文字在引言中提出了一些问题:

  • 为什么声明析构函数会隐藏移动语义?
  • 声明/ definig析构函数只隐藏移动语义或复制构造函数和复制赋值以及隐藏移动语义吗?

And*_*zej 22

事实上,"零规则"是关于生成特殊成员函数以及何时生成的其他内容.这是对课堂设计的一种态度.它鼓励您回答一个问题:

我班级管理资源吗?

如果是这样,则应将每个资源移动到其专用类,以便您的类仅管理资源(并且不执行任何其他操作)或仅累积其他类和/或执行相同的逻辑任务(但不管理资源).

这是更一般的单一责任原则的特例.

当你应用它时,你会立即看到对于资源管理类,你必须定义手动移动构造函数,移动赋值和析构函数(很少需要复制操作).对于非资源类,您不需要(事实上您可能不应该)声明以下任何一项:move ctor/assignment,copy ctor/assignment,destructor.

因此,名称中的"零":当您将类分离到资源管理和其他时,在"其他"中您需要提供零特殊成员函数(它们将被正确地自动生成.

C++中有一些规则(特殊成员函数的定义)禁止其他定义,但它们只会让您分心,无法理解零规则的核心.

有关更多信息,请参阅:

  1. https://akrzemi1.wordpress.com/2015/09/08/special-member-functions/
  2. https://akrzemi1.wordpress.com/2015/09/11/declaring-the-move-constructor/


Mat*_*son 6

几乎总是,如果你有一个析构函数(“做某事”),你应该遵循“三规则”,如果你想要移动语义,那么它就会变成“五规则”。

如果您的析构函数为空,则不需要它。所以这意味着一个非空的析构函数(因为如果不需要,你就不会拥有它!),那么你还需要在复制和赋值操作中做同样的事情,并且大概,移动构造和移动赋值将需要“做某事”,而不仅仅是传递实际内容。

当然,也有可能不是这样,但是编译器采取了“只有在析构函数为空的情况下才应用自动生成的移动函数”的方法,因为这是“安全”的方法。