C++ 2003, Section 12.6.2 "Initializing bases and members", paragraph 5, says:
Initialization shall proceed in the following order:
â” First, and only for the constructor of the most derived class as described below, virtual base classes shall be 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 class names in the derived class base-specifier-list.
â” Then, direct base classes shall be initialized in declaration order as they appear in the base-specifier-list (regardless of the order of the mem-initializers).
â” Then, nonstatic data members shall be initialized in the order they were declared in the class definition (again regardless of the order of the mem-initializers).
â” Finally, the body of the constructor is executed.
Consequently, the order in which constructor initializers appear is actually irrelevent, as the order in which they are executed is determined by external items, such as the order of the class fields. Reordering the initializers has no effect on the code execution, but can confuse programmers and lead to undefined behavior.
Non-Compliant Code Example
Code Block | ||||
---|---|---|---|---|
| ||||
class C { int a; int b; public: C() : b(3), a(b+1) {} }; |
In class c
's default constructor a
is initialized before b
because a
is declared before b
in the class body. Consequently a
's initialization depends on the unitialized value of b
, and so a
will likely hold garbage.
Implementation Details
MSVC 2008 compiles this code without warning. It sets c.b
to 3, and c.a
to -858993459.
G++ 4.3.3 issues a warning regarding the misordered initializers. It sets c.b
to 3 and c.a
to 32515.
Non-Compliant Code Example
This code reorders the initializers correctly:
Code Block | ||||
---|---|---|---|---|
| ||||
class C { int a; int b; public: C() : a(b+1), b(3) {} }; |
This code is still noncompliant, but now the error is obvious, a
clearly depends on b
despite being initialized first.
Compliant Solution
This code resolves the dependency.
Code Block | ||||
---|---|---|---|---|
| ||||
class C { int a; int b; public: C() : a(4), b(a-1) {} }; |
Note that it is perfectly reasonable for initializers to depend on previously initialized values.
Risk Assessment
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
OOP37-CPP | medium | probable | medium | P8 | L2 |
Bibliography
[Lockheed Martin 05] AV Rule 75 Members of the initialization list shall be listed in the order in which they are declared in the class.
[ISO/IEC 14882-2003] Section 12.6.2 "Initializing bases and members"
OOP36-CPP. Do not assume that copy constructor invocations will not be elided 13. Object Oriented Programming (OOP) 14. Concurrency (CON)