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!

2
  • Here's some info. I think it's just a way to be explicit. Commented May 16, 2014 at 14:47
  • Note that on copy constructors and destructors, being explicit can inhibit the generation of implict constructors: stackoverflow.com/questions/4819936/… Commented May 16, 2014 at 14:53

3 Answers 3

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. 
Sign up to request clarification or add additional context in comments.

Comments

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.

8 Comments

There is probably a difference when A is value initialized since A() = default is considered as not user-defined constructor
@privatedatapublicchannel2 very good point.
@privatedatapublicchannel2 I'm not so sure. Do you have an example?
@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). :-/
@juanchopanza see my edit above.
|
-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!) }; 

1 Comment

There is probably a difference also when A is value initialized