The Initialization List’s Illusionist Show

Consider the following  source:

 #include "b.h"
    class A
    {
    public:
        A();
        int get_i();

    private:
        B b;
        int i;
    };
a.h

 

#include "a.h" 
#include < iostream >

 A::A() : i(100), b(this){} 
 int A::get_i(){ return i; }
a.cpp
class A;
class B
{
public:
    B(A* _a);

private:
    A* a;
};
b.h
#include "a.h"
#include "b.h"
#include <iostream>

B::B( A* _a) : a(_a) 
{
  std::cout << "running B constructor "  << '\n';
  std::cout << "A::i value : " << a->get_i() << '\n';
} 
b.cpp
#include "a.h"
int main(void)
{
    A a;
    return 0;
}
main.cpp

Looking at the A class constructor’s  code you might expect the output to be:


Running B constructor
A::i value : 100

However,  after running the code on my  machine I got:

Running B constructor
A::i value : 1866555446

b  is the last member in the initialization list.  More to the point, it is located after the i member variables.  Yet, It appears as if i contains junk value when the B::B() constructor retrieves its value through the a this pointer.

So, what’s going on?

As a general principal, Having this in an initialization list should be done with some care.   However,  in this specific example,  the root cause is C++’s take on an illusionist act:  While the developer is busy carefully positioning variables in the initialization list, he is unaware the initialization order was already set without him noticing!

Variables initialization order is set by the order the variables are declared in the class,  not by the order they appear in the initialization list.  b is declared in  A  before i.  So,  when an A  object is constructed, The b member (declared first A class deceleration) is initialized first with the value supplied by the initialization list. The supplied value happen’s to be a pointer to a  half-baked A object with an uninitialised i member producing the junk value.

Conclusion

Declaring class variables doesn’t seem significate beyond the simple act of specifying data members needed to define the object’s state.  In effect, the class member declaration is important in subtle ways,  from object initialization to the way it is layout in memory.

Leave a Reply

Your email address will not be published. Required fields are marked *