The member initializer list for a class constructor allows members to be initialized to specified values as well as 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 C++ Standard, [class.base.init], paragraph 11 [ISO/IEC 14882-2014]:
...
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 in an order other than the in canonical one order can result in undefined behavior, such as reading uninitialized memory.
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.
...
In this noncompliant code example, the member initializer list for C::C()
attempts to initialize SomeVal
first , and then to initialize DependsOnSomeVal
to a value dependent on SomeVal
. However, since Because the declaration order of the member variables does not match the member initializer order, attempting to read the value of SomeVal
results in an unspecified value being stored into DependsOnSomeVal.
...
In this noncompliant code example, the derived class, D
, attempts to initialize the base class, B1
, with a value obtained from the base class, B2
. However, because B1
is initialized before B2
due to the declaration order in the base class specifier list, the results are resulting behavior is undefined.
Code Block | ||||
---|---|---|---|---|
| ||||
class B1 { int Val; public: B1(int V) : Val(V) {} }; class B2 { int OtherVal; public: B2(int V) : OtherVal(V) {} int getOtherVal() const { return OtherVal; } }; class D : B1, B2 { D(int A) : B2(A), B1(getOtherVal()) {} }; |
...
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:
...
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
| 4053, 4056, 4058 | ||||||||
Clang |
| -Wreorder |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
...
Bibliography
[ISO/IEC 14882-2014] | 12.6.2, "Initializing Bases and Members" |
[Lockheed Martin 05] | Rule 75, "Members of the initialization list shall be listed in the order in which they are declared in the class" |
...