Why is this an issue?
In a C++ class, all member variables of a type with an implicit or explicit constructor will be automatically initialized. This is not the case for
the others: if no initialization is explicitly written, the variable will be left uninitialized.
This comes with all the risks associated with uninitialized variables, and these risks propagate to all the classes using the faulty class as
a type. This is all the more surprising that most programmers expect a constructor to correctly initialize the members of its class (this is its
raison d’être after all).
To avoid such situations, all non class type fields should always be initialized (in order of preference):
- With an in-class initializer
- In the initialization list of a constructor
- In the constructor body
See {rule:cpp:S3230} for more details about this order.
Noncompliant code example
class C {
int val = 42;
};
class S {
public:
C c;
int i;
int j;
S() : i(0) {} // Noncompliant: this->j is left uninitialized
S(bool) : i(0), j(0) {}
};
class T {
public:
S s;
T() : s() {} // Noncompliant: s.j is left uninitialized
T(bool b) : s(b) {}
};
class U {
public:
T t;
U() : t() {} // Noncompliant: t.s.j is left uninitialized
};
Compliant solution
class C {
int val = 42;
};
class S_fixed {
public:
C c;
int i;
int j;
S_fixed() : i(0), j(0) {} // Compliant
S_fixed(bool) : i(0), j(0) {}
};
class T_fixed {
public:
S _fixed s;
T_fixed() : s() {} // Compliant
T_fixed(bool b) : s(b) {}
};
class U {
public:
T t;
U() : t() { t.s.j = 0; } // Compliant
};
Exceptions
Aggregate classes do not initialize most of their data members, but allow their users to use nice and flexible initialization syntax. They will be
ignored by this rule (but are the subject of {rule:cpp:S5558}).
Resources