views:

337

answers:

2

I've run into the following a few times with initializer lists and I've never been able to explain it well. Can anyone explain why exactly the following fails (I don't have a compiler to catch typos, so bear with me):

class Foo
{
 public:
  Foo( int i ) : m_i( i ) {}  //works with no problem

  int getInt() {return m_i;}

  ~Foo() {}
 private:
  int m_i;
};

class Bar
{
 public:
  Bar() : 
   m_foo( 5 ),           //this is ok 
   m_myInt( m_foo.getInt() ) //runtime error, seg 11
  {}

  ~Bar() {}
 private:
        Foo m_foo;
  int m_myInt;


};

When trying to call member functions of members initialized higher up the initializer list, I get seg faults. I seem to recall this is a known problem (or perhaps somehow by design) but I've never seen it well described. The attached example is contrived with plain old data types, but substitute the Bar::m_myInt with another object lacking a default (empty) constructor and the issue is more real. Can anyone enlighten me?

+8  A: 

The order of initialization is independent of the order of the elements in the initialization list. The actual order is that of the members in the class definition. That is, in your example m_foo will be initialized before m_myInt not because of the initialization list, but because the member appears first in the class.

The concrete example that you have posted should compile and run without problems.

David Rodríguez - dribeas
In the case of gcc, you can pass it `-Wreorder` and it will warn if you mess up
Michael Mrozek
Yup this is whats biting me! I had it switched in my head. I thought initialization order was based on initializer list order not class definition order. Thanks for clearing that up!
awm129
+4  A: 

Data members are initialized in the order listed in the class declaration (the order under private: in your example). The order given in the initializer list has no barring on construction order.

So, in your example, reordering the data members like so can cause the undefined behavior:

private:
    int m_myInt;
    Foo m_foo;

Is it possible that the order of the data members was actual different than you've shown?

Jon-Eric
yes, my example should have the private members of Bar flipped to fully illustrate the issue. thanks for your help!
awm129