Objects should be initialized as soon as they are declared. It will be implicitly the case if they have a default constructor, as this latter will
be called, but otherwise the initialization must be explicit. Even when an object has a default constructor, it may be interesting to use another more
relevant constructor to directly give the the object its right value.
Such direct initialization increases the readability of the code:
- seeing the initial value of a variable is usually a good indicator of its purpose,
- waiting until we know a good initial value before declaring a variable can lead to a reduced variable scope,
- it makes reasoning on the source code simpler: we remove the burden of having to know if a variable is initialized at a specific point in the
code,
- it is a first step that can lead to the possibility of declaring the variable
const, which further simplifies reasoning,
- it is also a first step toward declaring it
auto, which could increase readability by shifting the focus away from the exact type.
Please note that the intent of the rule is not to initialize any variable with some semi-random value, but with the value that is meaningful for
this variable.
This rule raises an issue when a local variable of a built-in or pointer type is declared without an initial value.
The related rule S836 detects situations when a variable is actually read before being initialized, while this rule promotes the good
practice of systematically initializing the variable.
Noncompliant code example
double init1();
double init2();
double init3();
double init4();
void f(bool b) {
int i; // Noncompliant
string s; // Compliant: default constructor will be called, but we could probably find a better value
double d1; // Noncompliant
double d2; // Noncompliant
if (b) {
d1 = init1();
d2 = init2();
} else {
d1 = init3();
d2 = init4();
}
}
Compliant solution
double init1();
double init2();
double init3();
double init4();
std::pair<double, double> init(bool b) {
return b ? std::make_pair(init1(), init2()) : std::make_pair(init3(), init4());
}
void f(bool b) {
int i = 0;
string s;
auto [d1, d2] = init(b);
}
// Or:
void f(bool b) {
auto [d1, d2] = [b](){
if (b) {
return std::make_pair(init1(), init2());
} else {
return std::make_pair(init3(), init4());
}
}();
}
Exceptions
Buffers can be left uninitialized as long as they are written into immediately after their declarations.
int buf[10]; // allowed but it should be initialized right after the declaration