What is the difference between constructor “=default” and the compiler generated constructor in C++?

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.

Leave a Comment