Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

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. According to the The C++ Standard, [class.base.init], paragraph 11 [ISO/IEC 14882-2014], states the following:

In a non-delegating constructor, initialization proceeds in the following order:
— First, and only for the constructor of the most derived class, virtual base classes are initialized in the order they appear on a depth-first left-to-right traversal of the directed acyclic graph of base classes, where “left-to-right” is the order of appearance of the base classes in the derived class base-specifier-list.
— Then, direct base classes are initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
— Then, non-static data members are initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
— Finally, the compound-statement of the constructor body is executed.
[Note: The declaration order is mandated to ensure that base and member subobjects are destroyed in the reverse order of initialization. —end note]

...

In this noncompliant code example, the member initializer list for C::C() attempts to initialize SomeVal someVal first and then to initialize DependsOnSomeVal dependsOnSomeVal to a value dependent on SomeValsomeVal. Because the declaration order of the member variables does not match the member initializer order, attempting to read the value of SomeVal someVal results in an unspecified value being stored into DependsOnSomeVal dependsOnSomeVal.

Code Block
bgColor#FFcccc
langcpp
class C {
  int DependsOnSomeValdependsOnSomeVal;
  int SomeValsomeVal;
 
public:
  C(int val) : SomeValsomeVal(val), DependsOnSomeValdependsOnSomeVal(SomeValsomeVal + 1) {}
};

Compliant Solution

This compliant solution changes the declaration order of the class member variables so that the dependency can be ordered properly in the constructor's member initializer list:.

Code Block
bgColor#ccccff
langcpp
class C {
  int SomeValsomeVal;
  int DependsOnSomeValdependsOnSomeVal;
 
public:
  C(int val) : SomeValsomeVal(val), DependsOnSomeValdependsOnSomeVal(SomeValsomeVal + 1) {}
};

Note that it It is reasonable for initializers to depend on previously initialized values.

...

Code Block
bgColor#FFcccc
langcpp
class B1 {
  int Valval;
 
public:
  B1(int Vval) : Valval(Vval) {}
};

class B2 {
  int OtherValotherVal;
 
public:
  B2(int VotherVal) : OtherValotherVal(VotherVal) {}
  int getOtherValget_other_val() const { return OtherValotherVal; }
};

class D : B1, B2 {
public:
  D(int Aa) : B2(Aa), B1(getOtherValget_other_val()) {}
};

Compliant Solution

This compliant solution initializes both base classes using the same value from the constructor's parameter list instead of relying on the initialization order of the base classes:.

Code Block
bgColor#ccccff
langcpp
class B1 {
  int Valval;
 
public:
  B1(int Vval) : Valval(Vval) {}
};

class B2 {
  int OtherValotherVal;
 
public:
  B2(int VotherVal) : OtherValotherVal(VotherVal) {}
};

class D : B1, B2 {
public:
  D(int Aa) : B1(Aa), B2(Aa) {}
};

Exceptions

Anchor
OOP53-EX0
OOP53-EX0
OOP53-CPP-EX0: Constructors that do not use member initializers do not violate this rule.

Risk Assessment

Rule

Severity

Likelihood

Remediation Cost

Priority

Level

OOP53-CPP

Medium

Unlikely

Medium

P4

L3

Automated Detection

Tool

Version

Checker

Description

PRQA QA-C++

  Include PagePRQA QA-C++_VPRQA QA-C++_V

4053, 4056, 4058

 

Astrée

Include Page
Astrée_V
Astrée_V

initializer-list-order
Fully checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC++-OOP53
Clang
Include Page
Clang_V
Clang_V
-Wreorder
CodeSonar
Include Page
CodeSonar_V
CodeSonar_V

LANG.STRUCT.INIT.OOMI

Out of Order Member Initializers

Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C++4053
Klocwork
Include Page
Klocwork_V
Klocwork_V
CERT.OOP.CTOR.INIT_ORDER
LDRA tool suite
Include Page
LDRA_V
LDRA_V

206 S

Fully implemented

Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V

CERT_CPP-OOP53-a

List members in an initialization list in the order in which they are declared
Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C++: OOP53-CPPChecks for members not initialized in canonical order (rule fully covered)
RuleChecker
Include Page
RuleChecker_V
RuleChecker_V
initializer-list-order
Fully checked
SonarQube C/C++ Plugin
Include Page
SonarQube C/C++ Plugin_V
SonarQube C/C++ Plugin_V
S3229
Clang Include PageClang_VClang_V-Wreorder 

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

Bibliography

[ISO/IEC 14882-2014]Subclause 12.6.2, "Initializing Bases and Members"
[Lockheed Martin
05
2005]AV Rule 75, Members of the initialization list shall be listed in the order in which they are declared in the class

...


...

Image Modified Image Modified Image Modified