The synthesized default constructor

I'm reading about constructors in C++ Primer and can't seem to figure out what the difference is between an empty default constructor and the default constructor synthesized by the compiler.

Please compare the examples given below and explain the difference between class A and B.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <string>

struct A {
    A() {}                  // Empty default constructor
    A(const std::string &str): s(str) {}
    std::string s = "foo";  // In-class initialization
    int v = 1;              // In-class initialization
};

struct B {
    B() = default;          // Use synthesized version.
    B(const std::string &str): s(str) {}
    std::string s = "bar";  // In-class initialization
    int v = 2;              // In-class initialization
};


It seems to me like A() and B() do exactly the same thing.

The compiler will first look for the initializer list, which is missing in both examples, so it will use in-class initializers instead. If I did not provide any in-class initializers the int would have been undefined in both objects. So what is the use of "= default"?
Yes, they do exacly the same thing:
Standard wrote:
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


But they do not behave the same. For example definition of POD types requires classes to not have any user-provided constructors (compiler synthesized, even explicitely generated like in your second case, are fine). So things like is_trivial, is_pod, std::is_trivially_default_constructible, etc will fail on your first example.
Last edited on
I'm afraid that went completely over my head. Do you mean that in order to preserve the "POD status" of the object itself, it must have no user-defined constructors? Only a default constructor defined with = default will do?

No, that doesn't make any sense to me. I tried the code below and none of the class types passes as POD.

1
2
3
4
5
6
7
8
int main()
{
    std::cout << std::boolalpha
              << "A: " << std::is_pod<A>::value << std::endl
              << "B: " << std::is_pod<B>::value << std::endl
              << "int: " << std::is_pod<int>::value << std::endl;
    return 0;
}



A: false
B: false
int: true
I was talking in general. Both of your classes are not POD because they contain non-POD types in itself.

Only a default constructor defined with = default will do?
You do not have to declare it, because it will be generated automatically here.
One of the reasons to have =default in default constructor is to preserve is_trivial, is_trivially_default_constructible and similar for classes which have user defined constructors:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct Point
{
    double x;
    double y;
    Point(double x, double y) : x(x), y(y) {}
    Point() = default;
    Point(const Point&) = default;
};

struct Point2
{
    double x;
    double y;
    Point2(double x, double y) : x(x), y(y) {}
    Point2() {};
    Point2(const Point& other){};
};

int main()
{
    std::cout << std::boolalpha <<
                 " Point: " << std::is_trivial<Point>::value  << '\n' <<
                 "Point2: " << std::is_trivial<Point2>::value << std::endl;
}
 Point: true
Point2: false
Rule of thumb: if default constructor does what you need, do not use empty constructor instead, but use =default to explicitely tell that you need default constructor.
Last edited on
I need to read up on is_pod, is_trivial, is_trivially_default_constructible to understand in what situations these properties are important. Until then I will follow the recommendation to use = default. Thanks.
It is usually used by standard (or some third-party) library to select most optimized overloads (for example if class is_trivially_copyable and target is supporting it, std::copy can fallback to use memcpy instead of copying elements one by one.)
Another important distinguishing feature is that the class without any user-provided constructor (defaulted okay) is an an aggregate and you can initialize it with curly braces (not in this case because the converting constructor from string is present)
Topic archived. No new replies allowed.