Rule
-
Unmodified stack value variables should be const. This is based on C++ core guidlines for “const”. This is about readability/understandability. This shouldn’t include parameter values, which can be handled by rule S994 which is MISRA C++2008 rule 7-1-1. The C++ core guidelines excludes the cases of parameters. This rule should only handle values, as there are other rules which apply to pointers and references that can be made const.
Reasons for the rule: (From the C++ core guidelines):
-
Con.1
Immutable objects are easier to reason about, so make objects non-constonly when there is a need to change their value. Prevents accidental or hard-to-notice change of value.
Con.4
Prevent surprises from unexpectedly changed object values.
Example code:
void f()
{
int x = 7;
const int y = 9;
for (;;) {
// ...
}
// ...
}
As x is not const, we must assume that it is modified somewhere in the loop.
The key case is for value variables, but there is room for also a new rule for pointers (for when not wanting to use S994)
Non-compliant code
for (int i : c) cout << i << '\n'; // BAD: just reading
Compilant Code (fixing the above noncompliant code)
for (const int i : c) cout << i << '\n'; // just reading: const
Exceptions:
From the C++ core guidlines, it shouldn’t apply to variables which are function parameters, and variables which are returned. Currently S994 applies to function parameters, so S994 can be used instead of this rule if someone wants the stricter MISRA rule. But this new rule is needed when S994 is not wanted.
Exception examples:
A local variable that is returned by value and is cheaper to move than copy should not be declared
constbecause it can force an unnecessary copy.
std::vector<int> f(int i)
{
std::vector<int> v{ i, i, i }; // const not needed
return v;
}
Function parameters passed by value are rarely mutated, but also rarely declared
const. To avoid confusion and lots of false positives, don’t enforce this rule for function parameters.
void g(const int i) { ... } // pedantic
Also this rule should just apply to value variables, as there are other rules which apply to references e.g. C5350. Also it shouldn’t apply to global variables which have a rule S5421.
Should this apply to pointers. S994 applies to pointer parameters, but not pointer local variables. This new rule could apply to those cases, but it may be better to other new rules as well for those cases for when S994 is not suitable.
Exhaustive case:
void YetAnotherFunc(int* view) // Noncompliant //S994 - and new rule or another new rule for pointers
{
}
void YetAnotherFunc2(int& view) // Noncompliant //S995
{
auto b = view;
}
void AnotherFunc(int view) // Noncompliant //S994 - but NOT new rule - this scenario is the main case why S994 is not suitable
{
}
void myfunc()
{
std::string& s = getString(); // Noncompliant //S5350
auto x = s.size(); // modified
x++;
auto y = x; // Noncompliant //S994 - and new rule
int *z = &x; // Noncompliant - new rule or another one for local pointers?
std::vector<int> v{ i, i, i }; // const not needed
return v;
}
external references and/or language specifications
-
- C++ code guidelines: Rules Con.1 and Con.4, noting also the exceptions under Con.1
C++ Core Guidelines - A similar topic was raised before regarding S994, but S994 was deemed correct for enforce const for function parameters. This new request is not asking to modify S994, but add an alternative.
- C++ code guidelines: Rules Con.1 and Con.4, noting also the exceptions under Con.1
-
type : Code Smell
-
Tags: C++ core guidelines