Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 736
tommyk Avatar asked Nov 27 '15 12:11

tommyk


People also ask

What does a default destructor do?

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.

Is Default destructor virtual?

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)

How does a virtual destructor work?

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.

Are move constructors automatically generated?

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.


1 Answers

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.

like image 160
TartanLlama Avatar answered Sep 27 '22 01:09

TartanLlama