CERT.OOP.CTOR.INIT_ORDER

Write constructor member initializers in the canonical order.

The member initializer list for a class constructor allows members to be initialized to specified values and for base class constructors to be called with specific arguments. However, the order in which initialization occurs is fixed and does not depend on the order written in the member initializer list. Consequently, the order in which member initializers appear in the member initializer list is irrelevant.

The order in which members are initialized, including base class initialization, is determined by the declaration order of the class member variables or the base class specifier list. Writing member initializers other than in canonical order can result in undefined behavior, such as reading uninitialized memory.

Vulnerability and risk

Writing member initializers other than in canonical order can result in undefined behavior, such as reading uninitialized memory.

Mitigation and prevention

Always write member initializers in a constructor in the canonical order: first, direct base classes in the order in which they appear in the base-specifier-list for the class, then nonstatic data members in the order in which they are declared in the class definition.

Example

Copy
  class C_positive {
  
    int dependsOnSomeVal;
    int someVal;
  
  public:
    C_positive(int val) : someVal(val), dependsOnSomeVal(someVal + 1) {}  // uncompliant code
  };
  
 class C_negative {
   int someVal;                                              // adjust the declarations order
   int dependsOnSomeVal;
 
 public:
   C_negative(int val) : someVal(val), dependsOnSomeVal(someVal + 1) {}  //compliant code
 };
 
 class B1 {
   int val;
 
 public:
   B1(int val) : val(val) {}
 };
 
 class B2 {
   int otherVal;
 
 public:
   B2(int otherVal) : otherVal(otherVal) {}
   int get_other_val() const { return otherVal; }
 };
 
 class D_positive : B1, B2 {
 public:
   D_positive(int a) : B2(a), B1(get_other_val()) {}         // uncompliant code
 };
 
 class B1 {
   int val;
 
 public:
   B1(int val) : val(val) {}
 };
 
 class B2 {
   int otherVal;
 
 public:
   B2(int otherVal) : otherVal(otherVal) {}
 };
 
 class D_negative : B1, B2 {
 public:
   D_negative(int a) : B1(a), B2(a) {}                       // compliant code
 };