48

Example for code:

class Dog
{
private:
    int x;
public:
    Dog()=default;
};

Vs. this code:

class Dog
{
private:
    int x;
};

What is the difference between the constructor that is "=default" (the first code) and the constructor that the compiler creates (like the second code)?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Noya_G
  • 499
  • 4
  • 7
  • 7
    At least one difference: In C++20, having a user-declared constructor (even if you use the default implementation) will mean that your class no longer counts as an aggregate. – Nathan Pierson Aug 17 '21 at 17:20
  • Do you want to know the difference between the two constructors (as the title implies) or the reason for using `=default` (as the text implies). – Jeffrey Aug 17 '21 at 17:26
  • 3
    Which version of C++ are you concerned about? Different versions of the standard have treated the behavior differently – NathanOliver Aug 17 '21 at 17:26
  • 1
    Does this answer your question? [The new syntax "= default" in C++11](https://stackoverflow.com/questions/20828907/the-new-syntax-default-in-c11) – Pat. ANDRIA Aug 17 '21 at 17:35

3 Answers3

42

Dog() = default; is a user declared constructor (not to be confused with a user defined constructor). It is a defaulted default constructor. Typically you would use it when the class has other constructors but you still want the compiler to generate a default constructor (or rather a "defaulted default constructor". This is C++ terminology at its best. Note how the two "default"s have slightly different meaning).

A user declared constructor prevents a class from being an aggregate. From cppreference, only for C++20:

An aggregate is one of the following types:

  • array type
  • class type (typically, struct or union), that has
    • no private or protected direct non-static data members
    • no user-declared or inherited constructors
    • no virtual, private, or protected base classes
    • no virtual member functions

As an example, consider:

#include <iostream>
#include <type_traits>

class Dog {
    int x;
public:
    Dog()=default;
};

class Horse {
    int x;
};

class Swan {
public: 
    int x;
};

class Cow {
public:
    int x;
    Cow() = default;
};

int main() {
    std::cout << std::is_aggregate_v<Dog>;
    std::cout << std::is_aggregate_v<Horse>;
    std::cout << std::is_aggregate_v<Swan>;
    std::cout << std::is_aggregate_v<Cow>;
}

Output

0010

The first two, Dog and Horse, resemble your two versions of Dog. They are not aggregates, because they have private members. Swan is an aggregate, but Cow is not, because it has a user declared constructor.

Something that works with aggregates, but not with non-aggregates, is designated initializers (same cppreference page):

Swan s{.x=3};    // OK
Cow c{.x=4};     // Error: Cow is not an aggregate

TL;DR: I am not aware of a difference between your two Dogs, but in general the presence of a user declared constructor can make a difference.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • 11
    `defaulted default constructor` And people say C++ is a confusing language – Silvio Mayolo Aug 18 '21 at 21:05
  • Is there any reason why (oh my -- a why!) the standard authors chose to deny classes with defaulted default constructors aggregate status? After all, it's only making explicit something that was there all along. – Peter - Reinstate Monica Aug 19 '21 at 09:22
  • @Peter-ReinstateMonica as I understood it, it has something to do with backwards compatibility to C++11, or rather avoid surprises when same code behaves differently. I don't find the answer anymore that mentioned it. I'll have to do some research before I can add some explanation to this answer – 463035818_is_not_an_ai Aug 19 '21 at 09:27
  • @SilvioMayolo Making the distinction between the _specifically_ defaulted default constructor and a _default_ default default constructor. All you need is one more layer of abstraction ;) – Spencer Aug 19 '21 at 13:07
  • 2
    @Peter-ReinstateMonica: A default constructor can be defaulted outside the class declaration, in a single compilation unit and invisible to all other consumers of the class. So C++ had to choose between (a) defaulted inside and outside the class are the same and make the class non-aggregate or (b) defaulted inside the class is the same as compiler-generated and outside the class makes non-aggregate. – Ben Voigt Aug 19 '21 at 14:57
16

I'll limit the scope to a default constructor, as in the question's code and tag. For the most part, you'll get the same effect since = default; loosely means "give me the compiler-generated one". It's important to note what exactly having no declaration does:

If there is no user-declared constructor for class X, a non-explicit constructor having no parameters is implicitly declared as defaulted. An implicitly-declared default constructor is an inline public member of its class.

If your declaration changes any of these, it will no longer be the exact same as the implicit one. In the standard, Dog() = default; is a user-declared constructor, but not a user-provided constructor. There are a couple small differences between having a user-declared default constructor and having no constructor.

As mentioned, aggregates were fixed:

struct not_agg {
    not_agg() = delete;
    int x;
};

Before the fix, such a class could be created via aggregate initialization: not_agg{}. Naturally, this also extends to = default;. Per [dcl.init.aggr]:

An aggregate is an array or a class with

  • no user-declared or inherited constructors

There is also rationale given for this change in annex C:

Remove potentially error-prone aggregate initialization which may apply notwithstanding the declared constructors of a class.


An interesting, but very tiny difference is that a class with a user-declared constructor is not allowed to have non-static data members of the same name as the class:

class c {
    int c; // Okay
};

class c2 {
    c2() = default;
    int c2; // Error
};

This is due to [class.mem]/21:

In addition, if class T has a user-declared constructor, every non-static data member of class T shall have a name different from T.

chris
  • 60,560
  • 13
  • 143
  • 205
3
  1. Default declared constructors can be guarded with protected or private access. Not declared default constructors are always inline public members of their classes.
  2. = default constructors are instantiated like usual member functions, may be inline or not, they have strong linkage references in the second case. The compiler creates not declared default constructors as inline member functions with weak linkage references.
  3. As mentioned in the comments, =default constructors are user-defined constructors and their classes are not aggregate types.
273K
  • 29,503
  • 10
  • 41
  • 64
  • 5
    This doesn't really answer the question on if there is difference between the two class definitions. – NathanOliver Aug 17 '21 at 17:36
  • 1
    Is there the such question? **what is the different between constructor that is =default (the first code) to the constructor that the compiler create (like the second code)** I do not get there **difference between the two class definitions**. – 273K Aug 17 '21 at 17:38
  • Interesting: How can you make the `=default` constructor not inline? – Peter - Reinstate Monica Aug 19 '21 at 09:18
  • 2
    @Peter-ReinstateMonica Declare in the class without `=default`, then add `=default` in the definition. It makes it lose its magical properties though (e.g. value-initialization behaving differently from value-initialization). – HolyBlackCat Aug 19 '21 at 12:10
  • @HolyBlackCat I didn't know that's possible. That explains why a defaulted default constructor is not distinguished from other user-defined constructors and changes the properties of the class accordingly: The compiler cannot know in the general case how the user-defined constructor is implemented. – Peter - Reinstate Monica Aug 19 '21 at 13:16
  • @Peter-ReinstateMonica To be clear, if it's `=default`ed in class body, it gets magical properties (same as compiler-generated ctor). If it's `=default`ed outside, it loses them. – HolyBlackCat Aug 19 '21 at 13:53