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