You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 7 Next »

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

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:

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.

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

OBJ37-CPP

2 (medium)

2 (probable)

2 (medium)

P8

L2

References

[[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"


OOP06-CPP. Create a private copy constructor and assignment operator for non copyable objects      13. Object Oriented Programming (OOP)      OOP33-CPP. Do not slice polymorphic objects

  • No labels