5

I have a question about the default constructor in C++. For example in a class A, what is the difference between using this default constructor A(){}; or A() = default; ? And what is the general difference between them?

Thank you in advance!

rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • [Here's](http://en.wikipedia.org/wiki/C++0x#Explicitly_defaulted_and_deleted_special_member_functions) some info. I think it's just a way to be explicit. – keyser May 16 '14 at 14:47
  • Note that on copy constructors and destructors, being explicit can inhibit the generation of implict constructors: http://stackoverflow.com/questions/4819936/why-no-default-move-assignment-move-constructor – Bill Lynch May 16 '14 at 14:53

3 Answers3

6

A constructor defined as defaulted on the first declaration is considered not user-provided. This is essentially like being implicit in C++03. Such a constructor declaration is allowed in an aggregate class.

struct ag {
    ag() = default;

    int a;
    double b;
};

struct nag {
    nag() {}

    int a;
    double b;
};

ag a = { 5, 12. }; // OK
nag na = { 5, 12. }; // error: not an aggregate and no appropriate constructor

This rule only applies when = default appears inside the class. Given this class definition:

struct nag {
    nag();

    int a;
    double b;
}; 

then these constructor definitions would indeed be completely equivalent:

nag::nag() {} // 1
nag::nag() = default; // 2

An explicit default constructor usually disables empty copy-list-initialization syntax (= {}), and {} as an argument or return value. An explicitly-defaulted and explicit default constructor in an aggregate is confusingly exempt from this rule because aggregate initialization has higher precedence than constructor initialization. This provides a way to detect whether a class is an aggregate, but you probably should not do so.

struct sadistic {
    explicit sadistic() = default;

    // members
};

sadistic se = {}; // OK only if sadistic has no virtual functions, etc.
Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
1

The behavior of the default constructors is the same for A() {} and A() = default; per 12.1p6:

The implicitly-defined default constructor performs the set of initializations of the class that would be performed by a user-written default constructor for that class with no ctor-initializer (12.6.2) and an empty compound-statement.

The differences are:

  • whether the constructor is constexpr (an explicitly-defaulted constructor is constexpr if that would be valid),
  • whether the class is an aggregate (8.5.1p1), and
  • whether value-initialization results in the default constructor being called, if the explicitly-defaulted default constructor is trivial (8.5p7).

For the last point:

#include <iostream>

struct A { int i; A() = default; };
struct B { int j; B() {} };

int main() {
    int i = 42, j = 42;
    new (&i) A();
    new (&j) B();
    std::cout << i << std::endl;  // 0
    std::cout << j << std::endl;  // 42
}

So you might want to write a user-provided non-defaulted default constructor, if for example your class has trivial members that would be expensive to zero-initialize (e.g. a large array), but it's a very niche case.

ecatmur
  • 152,476
  • 27
  • 293
  • 366
  • There is probably a difference when A is value initialized since A() = default is considered as not user-defined constructor – 4pie0 May 16 '14 at 14:58
  • @privatedatapublicchannel2 very good point. – ecatmur May 16 '14 at 15:00
  • @privatedatapublicchannel2 I'm not so sure. Do you have an example? – juanchopanza May 16 '14 at 15:00
  • @privatedatapublicchannel2: It is more complicated than that: 8.4.2: _A function is user-provided if it is user-declared and not explicitly defaulted or deleted on its first declaration._ So there is a difference between user-provided and user-declared. Moreover a function can be declared as defaulted in the second declaration and be user-provided and explicitly defaulted at the same time! (but not user-declared). :-/ – rodrigo May 16 '14 at 15:05
  • @juanchopanza see my edit above. – ecatmur May 16 '14 at 15:05
  • @ecatmur I think this may be a bug. AFAIK in C++11 a value initialization should perform a *zero* initialization of the data members (this was not the case in C++03.) But I will have to look this up, again... – juanchopanza May 16 '14 at 15:07
  • @juanchopanza yes, example: http://ideone.com/k8mBrd – 4pie0 May 16 '14 at 15:08
  • @ecatmur Thanks for the reference. I had managed to convince myself there had been change in c++11 here, but the behaviour is what it had always been. – juanchopanza May 16 '14 at 15:22
-1

There is not a lot of differences:

The old syntax (note that the ; is not needed):

A() {}

is available since the first days of C++. It will default construct every base class and member variable.

The new C++11 syntax:

A() = default;

does exactly the same, but it is explicit about being default, so you (or the compiler) don't have to check if the braces are really empty.

Note that if a class have no declared constructors, the compiler will add one for you.

CORRECTION: There is a difference if the default constructor is deleted, that is, the class implicit default constructor is not valid. In this case the {} is a syntax error, while the =default is like a deleted definition:

struct S
{
    int &r;  //non default constructible

    S() {} //error: uninitialized reference S::r;
    S() = default; //ok: deleted constructor
    S() = delete;  //also ok (but not both!)
};
rodrigo
  • 94,151
  • 12
  • 143
  • 190