I originally posted this as a question only about destructors, but now I'm adding consideration of the default constructor. Here's the original question:
If I want to give my class a destructor that is virtual, but is otherwise the same as what the compiler would generate, I can use
=default
:class Widget { public: virtual ~Widget() = default; };
But it seems that I can get the same effect with less typing using an empty definition:
class Widget { public: virtual ~Widget() {} };
Is there any way in which these two definitions behave differently?
Based on the replies posted for this question, the situation for the default constructor seems similar. Given that there is almost no difference in meaning between "=default
" and "{}
" for destructors, is there similarly almost no difference in meaning between these options for default constructors? That is, assuming I want to create a type where the objects of that type will be both created and destroyed, why would I want to say
Widget() = default;
instead of
Widget() {}
?
I apologize if extending this question after its original posting is violating some SO rules. Posting an almost-identical question for default constructors struck me as the less desirable option.
They are both non-trivial.
They both have the same noexcept specification depending upon the noexcept specification of the bases and members.
The only difference I'm detecting so far is that if
Widget
contains a base or member with an inaccessible or deleted destructor:Then the
=default
solution will compile, butWidget
won't be a destructible type. I.e. if you try to destruct aWidget
, you'll get a compile-time error. But if you don't, you've got a working program.Otoh, if you supply the user-provided destructor, then things won't compile whether or not you destruct a
Widget
:The important difference between
and
is that default constructor defined with
B() = default;
is considered not-user defined. This means that in case of value-initialization as inspecial kind of initialization that doesn't use a constructor at all will take place and for built-in types this will result in zero-initialization. In case of
B(){}
this won't take place. The C++ Standard n3337 § 8.5/7 saysFor example:
possible result:
http://ideone.com/k8mBrd
This is a completely different question when asking about constructors than destructors.
If your destructor is
virtual
, then the difference is negligible, as Howard pointed out. However, if your destructor was non-virtual, it's a completely different story. The same is true of constructors.Using
= default
syntax for special member functions (default constructor, copy/move constructors/assignment, destructors etc) means something very different from simply doing{}
. With the latter, the function becomes "user-provided". And that changes everything.This is a trivial class by C++11's definition:
If you attempt to default construct one, the compiler will generate a default constructor automatically. Same goes for copy/movement and destructing. Because the user did not provide any of these member functions, the C++11 specification considers this a "trivial" class. It therefore legal to do this, like memcpy their contents around to initialize them and so forth.
This:
As the name suggests, this is no longer trivial. It has a default constructor that is user-provided. It doesn't matter if it's empty; as far as the rules of C++11 are concerned, this cannot be a trivial type.
This:
Again as the name suggests, this is a trivial type. Why? Because you told the compiler to automatically generate the default constructor. The constructor is therefore not "user-provided." And therefore, the type counts as trivial, since it doesn't have a user-provided default constructor.
The
= default
syntax is mainly there for doing things like copy constructors/assignment, when you add member functions that prevent the creation of such functions. But it also triggers special behavior from the compiler, so it's useful in default constructors/destructors too.