Const and Const Correctness
const
is a keyword we can use to make variables "constant", meaning their values can not be changed after initialization. We can also use const
for pointers, function parameters and member functions.
The use of const
is as much about properly documenting the intention behind our code as it is enforcing program safety.
Const correctness
The idea behind const
correctness is to more clearly express the intent of our code to anyone reading it (compiler included).
Guidelines
- Use
const
with variables that should not be modified after initialization - Pass function parameters as
const
references if the functions do not need to modify them - Declare member functions as
const
if they do not modify the object on which they are called
Use const
as often as possible to inform the reader (and compiler) that the value being passed as a variable, pointer, function parameter, or member function will not be modified or mutated in any way.
const Variables
Below we have two values, where one has the const
qualifier and the other does not.
int Foo = 5; // non-const
const int Bar = 22; // const
From this declaration alone, we know (as does the compiler) that Foo
can be modified, but Bar
is meant to be a read-only value.
If we attempted to reassign the value of Foo
, the compiler would allow it:
Foo = 8; // allowed
But if we attempted to reassign the value of Bar
, the compiler would complain that the value can't be reassigned because it is read-only.
Bar = 32; // error, can not mutate a read-only value
This practice helps to document to anyone reading the code the programmer's intent behind the use of the variable.
const Function Parameters
We can also qualify function parameters as being const
, telling us (and the compiler) which values are mutable and which are immutable.
The function below takes 3 parameters, with two marked as const
.
void ModifyValues(string NewValX, const int NewValY, const float NewValZ)
{
NewValX = "new string value"; // allowed
NewValY = 10; // error, can not mutate a read-only value
NewValZ = 3.4f; // error, can not mutate a read-only value
}
The function scope does not allow ValY
or ValZ
to be mutated because of the const
qualifier, no matter the values passed in.
This strict enforcement also applies when a non-const value is passed into a const
qualified function parameter.
string ValX = "original string value"; // non-const
int ValY = 5; // non-const
const float ValZ = 1.0f; // const
void ModifyValues(string NewValX, const int NewValY, const float NewValZ)
{
NewValX = "new string value"; // allowed
NewValY = 10; // error; can not mutate a read-only value
NewValZ = 3.4f; // error, can not mutate a read-only value
}
In the example above, although int ValY = 5;
is a non-const variable, the const
qualifier in the ModifyValues()
function prevents the value within the function scope from being mutated.
const Member Functions
We can also qualify member functions as const
which guarantees that the function will not mutate the state of the object (this
) when called.
void ModifyValues() {} // non-const member function
void GetValues() const {} // const member function
When a member function is qualified as const
, this does mean the const
member function is not allowed to call a non-const member function.
void ModifyValues() {} // non-const member function
void TryToGetCurrentValues() const {}
void GetValues() const // const member function
{
ModifyValues(); // error, const function can not call non-const function
TryToGetCurrentValues(); // allowed
}
Backlog
- Cover using
const
with pointers (pointers toconst
andconst
pointers)