C++ 11中自动生成特殊移动函数(构造函数和赋值运算符)的规则指定不能声明析构函数.据推测,如果你需要在破坏中做一些特别的事情,那么这一举动可能并不安全.
但是,对于多态中正确的析构函数调用,必须将基类的析构函数声明为虚拟(否则通过其基类的指针删除子类的实例将无法正确链接析构函数).
我假设,即使是一个空的析构函数也会阻止编译器自动生成一个特殊的移动函数.如:
class Base {
virtual ~Base() { }
};
Run Code Online (Sandbox Code Playgroud)
但是,您可以默认析构函数,如下所示:
class Base {
virtual ~Base() = default;
}
Run Code Online (Sandbox Code Playgroud)
问题1:这是否允许编译器自动生成特殊的移动函数?
但是,显式默认析构函数存在问题.至少在GCC 4.8.2的情况下,签名被隐式地改为noexcept.如:
class Base {
virtual ~Base() = default; // compiler changes to:
// virtual ~Base() noexcept;
}
Run Code Online (Sandbox Code Playgroud)
虽然我在析构函数中使用noexcept没有问题,但这会破坏以下"客户端"代码:
class Sub : public Base {
virtual ~Sub(); // this declaration is now "looser" because of no noexcept
}
Run Code Online (Sandbox Code Playgroud)
所以问题2更重要的是:有没有办法允许在C++ 11中自动生成特殊的移动函数,并允许正确的析构函数链接到子类(如上所述),所有这些都不会破坏子类("客户端")代码?
我试着通过阅读这篇博客来了解零的规则.IMO,它说如果你声明自己的析构函数,那么不要忘记创建移动构造函数并将赋值移动为默认值.
示例:
class Widget {
public:
~Widget(); // temporary destructor
... // no copy or move functions
};
Run Code Online (Sandbox Code Playgroud)
"添加析构函数会产生禁用生成移动函数的副作用,但由于Widget是可复制的,因此用于生成移动的所有代码现在都会生成副本.换句话说,向类中添加析构函数可能会导致 - 有效的动作可以用可能效率低下的副本无声地替换".
Scott Meyers的上述文字在引言中提出了一些问题: