默认的虚拟析构函数是否会阻止编译器生成的移动操作?

tom*_*myk 30 c++ move-semantics virtual-destructor c++11

灵感来自帖子为什么析构函数会禁用隐式移动方法的生成?,我想知道默认的虚拟析构函数是否也是如此,例如

class WidgetBase // Base class of all widgets
{
    public:
        virtual ~WidgetBase() = default;
        // ...
};
Run Code Online (Sandbox Code Playgroud)

由于该类旨在成为窗口小部件层次结构的基类,因此我必须定义其析构函数virtual,以避免在使用基类指针时出现内存泄漏和未定义的行为.另一方面,我不想阻止编译器自动生成移动操作.

默认的虚拟析构函数是否会阻止编译器生成的移动操作?

Tar*_*ama 26

是的,声明任何析构函数都会阻止移动构造函数的隐式声明.

N3337 [class.copy]/9: 如果类X的定义没有显式地声明一个移动构造函数,那么当且仅当一个移动构造函数被隐式声明为默认值时

  • X没有用户声明的复制构造函数,
  • X没有用户声明的复制赋值运算符,
  • X没有用户声明的移动赋值运算符,
  • X没有用户声明的析构函数,和
  • 移动构造函数不会被隐式定义为已删除.

声明析构函数并将其定义default用户声明的计数.

您需要声明移动构造函数并将其定义为您default自己:

WidgetBase(WidgetBase&&) = default;
Run Code Online (Sandbox Code Playgroud)

请注意,这将依次定义复制构造函数delete,因此您也需default要这样做:

WidgetBase(const WidgetBase&) = default;
Run Code Online (Sandbox Code Playgroud)

复制和移动赋值运算符的规则也很相似,所以default如果你需要它们就必须使用它们.