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:
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.
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.
(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.
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