【发布时间】:2015-12-02 12:06:23
【问题描述】:
C++ 标准委员会选择在定义自定义析构函数时删除隐式定义的移动赋值运算符的基本原理是什么?
【问题讨论】:
-
我不知道,所以我只能猜测:它可能来自
rule of 3,当您需要析构函数时,您还需要一个复制和赋值运算符。这也适用于移动运算符
标签: c++ c++11 destructor move-assignment-operator
C++ 标准委员会选择在定义自定义析构函数时删除隐式定义的移动赋值运算符的基本原理是什么?
【问题讨论】:
rule of 3,当您需要析构函数时,您还需要一个复制和赋值运算符。这也适用于移动运算符
标签: c++ c++11 destructor move-assignment-operator
来自 Scott Meyer 的 Effective Modern C++ Item 17(假设您了解 Rule of Three):
三规则的结果是用户声明的析构函数的存在表明简单的成员复制不太可能适合类中的复制操作。反过来,这表明如果一个类声明了一个析构函数,则可能不应该自动生成复制操作,因为它们不会做正确的事情。 [...]
然而,三法则背后的推理仍然有效,再加上观察到复制操作的声明排除了移动操作的隐式生成,这激发了 C++11 确实不 为具有用户声明的析构函数的类生成移动操作。
【讨论】:
这个想法是,任何默认生成的构造函数(复制构造函数、复制赋值或析构函数)的存在都表明一个类型需要进行某种特殊的资源管理。如果是这种情况,默认的移动操作可能不会做正确的事情。我不确定是否确实出现了默认生成的复制构造函数正常工作但默认生成的移动构造函数失败的示例。
解决方案是默认不生成移动操作更安全,特别是因为很容易要求相应的移动操作:只需添加一个= defaulted 实现。无论如何,该类显然已经做了一些特殊的事情(否则将没有析构函数)。
【讨论】:
= default这样的东西。实际上,人们甚至没有想到Rule of Three(这实际上是不正确的:为了强异常安全,有时需要实现赋值运算符,尽管不需要其他结构)。现在更改规则会破坏很多代码。也就是说,正如 KerrekSB 所说,简短的回答是:“历史性镇流器”