Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Order of calling constructors in one case C++

#include <iostream>
struct A
{
    A(){std::cout<<"A()"<<std::endl;}
};

template<typename T>
struct B
{
    A a;
    T b;
    B(){std::cout<<"B()"<<std::endl;}
};

int main()
{
    B<B<B<int> > > Test;
    return 0;
}

The odrer of calling constructors is

A()
A()
A()
B()
B()
B()

And i have no clue why is that. I thought it would be A B A B A B. Could you explain me why?

like image 407
NameOn Avatar asked Sep 28 '22 16:09

NameOn


2 Answers

This is actually straight forward, if it was like A B A B A B, then you would have trouble if you wanted to access b from the constructor of B, since the order you thought implies that first member a gets instantiated, then ctor runs, then b gets initialized. In reality, every member is instantiated (constructed etc.) first, then, the constructors are called.

like image 175
Fatih BAKIR Avatar answered Oct 05 '22 06:10

Fatih BAKIR


This is because member variables must be initialized before the body of the constructor is executed. Consider the following example:

struct A {
    int value;

    // Here we explicitly initialize 'value' with 5
    A() : value(5) { }
};

struct B {
    A a;

    B()
    {
        // This is perfectly valid and would print 5,
        // because 'a' has already been implicitly initialized
        // with its default constructor.
        std::cout << a.value;
    }
};

If this weren't the case, what value would you expect a to have in B's constructor? You'd run into all sorts of issues. Therefore, the default constructor of A must be implicitly called before the body of B().

Essentially, to make it more explicit, this is what is happening:

    // Initialize 'a' before body of constructor
    B() : a()
    {
        std::cout << a.value;
    }
like image 41
Julian Avatar answered Oct 05 '22 08:10

Julian