Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to make a destructor defaulted using =default?

Tags:

Although using =default for constructors is clear for me (i.e. forcing the compiler to create the default constructor while other ctors exist), I still cannot understand the difference between these two type of destructors:

  1. Those that use =default
  2. Those that are not defined explicitly and generated by compiler automatically.

The only thing that comes to my mind is that the group-1 destructors can be defined as virtual, but group-2 is always non-virtual. So, is that the only difference between them? Is there any scenarios that the compiler is not generating the destructor, but using =default forces the compiler to generate it?

p.s. I have checked lots of Qs in stackoverflow, but none of them answers my Q. Here are some relevant questions.

  1. Difference between =default and {} ctos/destructors
  2. Defaulting virtual destructors
  3. Difference between =default and empty dtrs

Edit 1: This Q on SO, focuses on disabling the default move constructors, that can be considered as ONE of the items mentioned in the accepted answer.

like image 457
Gupta Avatar asked Jun 27 '19 22:06

Gupta


1 Answers

(Several of the points below were already mentioned in comments or in the linked questions; this answer serves to organize and interrelate them.)

There are of course three ways to get a “simple destructor”:

struct Implicit {};
struct Empty {~Empty() {}};
struct Defaulted {~Defaulted()=default;};

Like a default (and not a copy or move) constructor, {} and =default; mean largely the same thing for destructors. The interesting properties of Defaulted are then those (combinations) that differ from both of the others.

Versus Empty the main difference is simple: the explicitly defaulted destructor can be trivial. This applies only if it is defaulted inside the class, so there is no difference between {} and =default; on an out-of-line definition. Similarly, being virtual removes any distinction, as does having any member or base class with a non-trivial destructor. There is also the distinction that an explicitly defaulted destructor can be implicitly defined as deleted. Both of these properties are shared with implicitly declared destructors, so we have to find a distinction from those as well.

Versus Implicit, an explicitly defaulted destructor suppresses move operations, can be declared private, protected, or noexcept(false), and in C++20 can be constrained (but not consteval). Very marginally, it can be declared constexpr to verify that it would be anyway. Declaring it inline doesn’t do anything. (It can also be out of line or virtual, but as stated above that can’t be a reason to use it.)

So the answer is “when you want a trivial (or potentially deleted) destructor that has other special properties”—most usefully, access control or noexcept status.

like image 166
Davis Herring Avatar answered Sep 28 '22 18:09

Davis Herring