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

时间:2022-09-06 12:49:07

Inspired by the post Why does destructor disable generation of implicit move methods?, I was wondering if the same is true for the default virtual destructor, e.g.

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

class WidgetBase // Base class of all widgets
{
    public:
        virtual ~WidgetBase() = default;
        // ...
};

As the class is intended to be a base class of a widget hierarchy I have to define its destructor virtual to avoid memory leaks and undefined behavior when working with base class pointers. On the other hand I don't want to prevent the compiler from automatically generating move operations.

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

Does a default virtual destructor prevent compiler-generated move operations?

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

1 个解决方案

#1


22  

Yes, declaring any destructor will prevent the implicit-declaration of the move constructor.

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

N3337 [class.copy]/9: If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

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

  • X does not have a user-declared copy constructor,
  • X没有用户声明的复制构造函数,
  • X does not have a user-declared copy assignment operator,
  • X没有用户声明的复制赋值运算符,
  • X does not have a user-declared move assignment operator,
  • X没有用户声明的移动赋值运算符,
  • X does not have a user-declared destructor, and
  • X没有用户声明的析构函数,和
  • the move constructor would not be implicitly defined as deleted.
  • 移动构造函数不会被隐式定义为已删除。

Declaring the destructor and defining it as default counts as user-declared.

声明析构函数并将其定义为默认值计为用户声明的。

You'll need to declare the move constructor and define it as default yourself:

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

WidgetBase(WidgetBase&&) = default;

Note that this will in turn define the copy constructor as delete, so you'll need to default that one too:

请注意,这将依次将复制构造函数定义为delete,因此您还需要默认该复制构造函数:

WidgetBase(const WidgetBase&) = default;

The rules for copy and move assignment operators are pretty similar as well, so you'll have to default them if you want them.

复制和移动赋值运算符的规则也非常相似,因此如果需要,您必须默认它们。

#1


22  

Yes, declaring any destructor will prevent the implicit-declaration of the move constructor.

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

N3337 [class.copy]/9: If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if

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

  • X does not have a user-declared copy constructor,
  • X没有用户声明的复制构造函数,
  • X does not have a user-declared copy assignment operator,
  • X没有用户声明的复制赋值运算符,
  • X does not have a user-declared move assignment operator,
  • X没有用户声明的移动赋值运算符,
  • X does not have a user-declared destructor, and
  • X没有用户声明的析构函数,和
  • the move constructor would not be implicitly defined as deleted.
  • 移动构造函数不会被隐式定义为已删除。

Declaring the destructor and defining it as default counts as user-declared.

声明析构函数并将其定义为默认值计为用户声明的。

You'll need to declare the move constructor and define it as default yourself:

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

WidgetBase(WidgetBase&&) = default;

Note that this will in turn define the copy constructor as delete, so you'll need to default that one too:

请注意,这将依次将复制构造函数定义为delete,因此您还需要默认该复制构造函数:

WidgetBase(const WidgetBase&) = default;

The rules for copy and move assignment operators are pretty similar as well, so you'll have to default them if you want them.

复制和移动赋值运算符的规则也非常相似,因此如果需要,您必须默认它们。