Whenever you logically do not alter a value or an object you should make it const
. By logically I do not mean every time you are technically allowed to, but every time it is logical in the context of your functions, classes and code.
A simple example could be a simple "get" function as seen in example 1, these functions should not modify the state of the class, and should therefore be marked constant, as this will help document your intent to the user, besides helping you ensure the invariance of the class.
There are situations where it makes sense to make an immutable object, as seen in example 2. It is not that often we see these in C++, but many other languages use them frequently. If it does not add any value to be able to change a certain member during an objects lifetime, you might as well make it const.
Passing const reference parameters gives you the performance benefits of the reference, but at the same time ensures that the source object is kept unmodified, which is both great documentation to the user, but also allows som optimizations to happen.
Having mentioned all these reasons, there are other reasons to use const
as briefly mentioned in the last paragraph, optimizations. When the compiler knows that something is constant and is not being altered it can enable some pretty clever optimizations, don't use const
for performance reasons though.
This is also why working around constness by (for instance) the const_cast
cast, which can cast away const
, can lead to some undesired behaviour. As an example check out the following:
#include <stdio.h>
static const int foo = 10;
int constsum(void) {
return foo + 5;
}
int main(int argc, char* argv[]) {
int a = constsum();
int* newFoo = const_cast<int*>(&foo);
*newFoo = 20;
int b = constsum();
printf("%d\n", a + b);
return 0;
}
As can be seen from this example (see code running here) this might not produce the desired result, as the code result in 30
being printed, and not as perhaps expected 40.
When examining the produced assembly we can see why (compiled into assembly):
constsum():
mov eax, 15
ret
main:
mov eax, 30
ret
The compiler simply inlines the values, as it can see that they constant, it does not take special care that the const_cast
is being used.
So const correctness, and use of const
is a valuable tool, that can benefit performance, and stability of your code, but also (and not to forget) it helps documenting your code.