[ Team LiB ] Previous Section Next Section

Gotcha #52: Inconsistent Ordering of the Member Initialization List

The order in which a class object's components are initialized is fixed to a precise order by the C++ language definition (see also Gotcha #49).

  • Virtual base class subobjects, no matter where they occur in the hierarchy

  • Nonvirtual immediate base classes, in the order they appear on the base class list

  • The data members of the class, in the order they are declared

This implies that any constructor for a class must perform its initializations in this order. Specifically, this implies that the order in which items are specified on a constructor's member initialization list is immaterial, as far as the compiler is concerned:



class C { 


 public:


   C( const char *name );


 private:


   const int len_;


   string n_;


};


// . . .


C::C( const char *name )


   : n_( name ), len_( n_.length() ) // error!!!


   {}


The len_ member is declared first, so it will be initialized before n_, even though its initialization appears after that of n_ on the member initialization list. In this case, we'll attempt to call a member function of an object that hasn't been initialized, with an undefined result.

It's considered good form to put the elements of the member initialization list in the same order as the base class and data members of the class; that is, in the order the initializations will actually be performed. To the extent possible, it's also good practice to avoid order dependencies within the member initialization list:



C::C( const char *name ) 


   : len_( strlen(name) ), n_( name )


   {}


See Gotcha #67 for the reasons why the initialization ordering is divorced from the ordering of the member initialization list.

    [ Team LiB ] Previous Section Next Section