C++ Member Variable Initialization Order

In C++, understanding the order in which class member variables are initialized is critical for preventing undefined behavior and difficult-to-track bugs. This article covers the fundamental rules governing non-static member variable initialization during object construction, clarifies the role of constructor initializer lists, and outlines the complete sequence of events from base class construction to the execution of the constructor body.

The Core Rule: Declaration Order

In C++, non-static member variables are always initialized in the exact order they are declared in the class definition.

The order in which members appear in a constructor's member initializer list has no effect whatsoever on the initialization sequence. Even if a constructor lists member variables in a different order, the compiler initializes them strictly according to their order of declaration within the class body.

class Example {
    int a;
    int b;

public:
    // 'a' is initialized first, then 'b', despite the order in the list
    Example(int val) : b(val), a(b + 1) {} 
};

In the example above, a will be initialized before b. Because a attempts to use b before b has been initialized, a will be assigned an indeterminate value, leading to undefined behavior. Modern compilers typically emit warnings (such as -Wreorder in GCC and Clang) when the order in the initializer list does not match the declaration order.

The Complete Construction Hierarchy

Member variable initialization is part of a broader, well-defined sequence that occurs whenever a C++ object is constructed:

  1. Virtual Base Classes: Virtual base class subobjects are initialized first, in depth-first, left-to-right order as they appear in the inheritance hierarchy.
  2. Direct Non-Virtual Base Classes: Direct base classes are initialized next, in the order they appear in the base-specifier list of the derived class declaration.
  3. Non-Static Data Members: Member variables are initialized in the order of their declaration within the class definition.
  4. Constructor Body: Once all base classes and member variables are fully initialized, the code inside the constructor's body executes.

In-Class Member Initializers (Default Member Initializers)

Introduced in C++11, in-class member initializers allow default values to be assigned directly at declaration:

class Config {
    int timeout = 30;
    int retries = 3;
};

These initializers do not alter the initialization order. Members are still initialized top-to-bottom as declared. If a constructor explicitly initializes a member in its initializer list, that explicit initialization overrides the in-class default.

Destruction Order

When an object's lifetime ends, destruction occurs in the exact reverse order of construction. Non-static member variables are destroyed first in the reverse order of their declaration, followed by the base classes in reverse order of their inheritance specification.