I thought the concept of "const-correctness" was pretty well defined, but when I talked to other people about it, it seemed we had different ideas of what it means. Some people say it's about a program having the "const" annotations in as many places as possible. Others define a program as const-correct if and only if there are no violations of constness where the const annotation is used (ie. it's a property that the compiler checks for you).
So I'd like to know, which of these functions are const correct:
struct Person {
string getName1() const { return _name; }
string getName2() { return _name; }
string getName3() const { _name = "John"; return _name; }
string getName4() { _name = "John"; return _name; }
string _name;
};
I've searched on the Internet for definitions but couldn't really find definite answer, and I also have suspicions that there might be a case of citogenesis at play. So could anyone provide any solid citation for a definition?
In my view "const correctness" means:
Everything that isn't intended to be modified should be marked as
const
.
This means that the compiler can tell you when you make a mistake. (It also possibly has implications for optimisations in certain conditions, but that's more of a secondary benefit and depends on a lot of other factors)
There are three basic places where this is useful:
Member functions can be marked const
, as in your examples. This means that your accesses to member variables from within that function will be as though the variables themselves were const
. (This is the example you've shown, although getName3()
won't work)
"Free" variables, local and member variables themselves may also be marked const
- once initialised they may not be changed. Example - local variable:
int f(int i) {
const int square = i*i;
// do something here that uses, but doesn't change square
return square;
}
Or free variable:
extern const double PI; // set somewhere else but not changed.
Or member variable:
class foo {
const int state; // can't be changed once constructed
foo(int s) : state(i) {}
};
Function arguments can also be marked const
, the definition can match a non-const declaration still:
void f(int i);
void f(const int i) {
// the fact that i is const is an implementation detail of f here
}
As a side note const
correctness for references is required in some cases:
void g(const std::string& s);
void f(std::string& s);
Of these two one can be used in more places:
g("hi"); // Fine
f("hi"); // Not fine - you can't bind a temporary to a reference
Of course if you meant to change s
then passing a temporary in makes little sense anyway.
Text from parashift:
It means using the keyword const to prevent const objects from getting mutated.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With