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.
Does a default virtual destructor prevent compiler-generated move operations?
The default destructor calls the destructors of the base class and members of the derived class. The destructors of base classes and members are called in the reverse order of the completion of their constructor: The destructor for a class object is called before destructors for members and bases are called.
The destructor is not user-provided (meaning, it is either implicitly declared, or explicitly defined as defaulted on its first declaration) The destructor is not virtual (that is, the base class destructor is not virtual)
In simple terms, a virtual destructor ensures that when derived subclasses go out of scope or are deleted the order of destruction of each class in a hierarchy is carried out correctly. If the destruction order of the class objects is incorrect, in can lead to what is known as a memory leak.
If a copy constructor, copy-assignment operator, move constructor, move-assignment operator, or destructor is explicitly declared, then: No move constructor is automatically generated. No move-assignment operator is automatically generated.
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
- X does not have a user-declared copy constructor,
- X does not have a user-declared copy assignment operator,
- X does not have a user-declared move assignment operator,
- X does not have a user-declared destructor, and
- 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:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With