Initialization order issues

163 views Asked by At

Given the code sample:

class B {
    //Some contents.
};

class C {
    private:
        B& b;
};

class A {
    private:
        B b;
        C c;
};

Class C has a reference to a b, so it needs to be initialized with it. Class A contains an instance of B and an instance of C.

My question is: Can I initialize the C instance in A with the B instance in A (assuming I did bother to put the constructors in)? Secondly, do I need to perform any explicit initialization of the B in A, or is it default initialized since its a class type within a class?

4

There are 4 answers

2
Seth Carnegie On BEST ANSWER

Member variables are initialised in the order that they are declared in the class declaration (even if you have them in a different order in the initialisation list of the constructor), so yes, by the time c is being initialised, b will be initialised, and you can use b to initialise c.

As Ricardo Cardenes notes, it will still work even if you declare c before b in the class definition (which means you will pass C::C a reference to an uninitialised B) however you cause undefined behaviour if you use the object inside C::C. It's safer to declare b first, because although you may not use b inside C::C now, you might in the future and forget that the reference refers to an uninitialised B, and cause UB.

And no, you do not have to explicitly initialise b (unless it is POD) unless you don't want it to be default-constructed. So this code would be what you want (again, if B isn't POD):

A::A() : c(b) { }
3
Joachim Isaksson On

Yes, since C only contains a reference to a B and not a separate instance, you can put a constructor in C and let A.C.b reference A.B.

B and C inside A are both instantiated/constructed automatically when you create an instance of A.

3
Grizzly On

To your first question: you can initialize it by writing constructors like this:

C::C(B& bInst): b(bInst){}
A::A():b(), c(b) {}

Of course if your constructor of C actually uses b (instead of just its address), you need to ensure that the initialization order stays the same, so b must be declared before c, since members are initialized in the order they are declared in (even if the initializaiton list puts them in a different order).

And no you don't need to explicitly initialize B, since it will be default constructed if you don't. Of course if B is a POD this means remaining it uninitialized (while explicitely initializing it using b() in the initializer list of A() would initialize it to 0).

0
Lightness Races in Orbit On

Can I initialize the C instance in A with the B instance in A (assuming I did bother to put the constructors in)

Sure.

Secondly, do I need to perform any explicit initialization of the B in A, or is it default initialized since its a class type within a class?

No, that's fine.