How is "=default" different from "{}" for default constructor and destructor?
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:
struct Trivial
{
int foo;
};
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:
struct NotTrivial
{
int foo;
NotTrivial() {}
};
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:
struct Trivial2
{
int foo;
Trivial2() = default;
};
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.
The important difference between
class B {
public:
B(){}
int i;
int j;
};
and
class B {
public:
B() = default;
int i;
int j;
};
is that default constructor defined with B() = default;
is considered not-user defined. This means that in case of value-initialization as in
B* pb = new B(); // use of () triggers value-initialization
special 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 says
To value-initialize an object of type T means:
— if T is a (possibly cv-qualified) class type (Clause 9) with a user-provided constructor (12.1), then the default constructor for T is called (and the initialization is ill-formed if T has no accessible default constructor);
— if T is a (possibly cv-qualified) non-union class type without a user-provided constructor, then the object is zero-initialized and, if T’s implicitly-declared default constructor is non-trivial, that constructor is called.
— if T is an array type, then each element is value-initialized; — otherwise, the object is zero-initialized.
For example:
#include <iostream>
class A {
public:
A(){}
int i;
int j;
};
class B {
public:
B() = default;
int i;
int j;
};
int main()
{
for( int i = 0; i < 100; ++i) {
A* pa = new A();
B* pb = new B();
std::cout << pa->i << "," << pa->j << std::endl;
std::cout << pb->i << "," << pb->j << std::endl;
delete pa;
delete pb;
}
return 0;
}
possible result:
0,0
0,0
145084416,0
0,0
145084432,0
0,0
145084416,0
//...
http://ideone.com/k8mBrd