The many uses of const in C++
const
for making constants
There are cases when one needs to declare variables that never change their values throughout their lifetime. These are known as constants. The const
keyword is used for declaring such constants.
Syntax:
const type name = value;
OR
type const name = value;
Examples:
// integer constant
const int K = 10;
// int const K = 10; // equivalent to the first one
// string constant
const std::string GREET = "Hello";
// double constant
const double PI = 3.1416;
As these are constants, their values can never be changed. That's the reason they have to be initialized at the time of declaration. Decalaration and initialization cannot be broken down into multiple statements.
const int K;
K = 10; // error
Note: It's a convention to name constants with uppercase letters.
const
in instance variables
We saw that const
variables must be initialized at the time of declaration. But, what about instance variables of a class? What if we want constants as instance variables?
class Sample {
private:
const int M;
// other declarations
};
Here, the constant M
is not initialized. That's okay for an instance variable. One can always initialize the constant in the constructor of the class. This is obvious as only when an object (instance) of the class is created, memory will be allocated for the instance variables. So M
doesn't exist in the memory when the class is just declared. When an object is created, only then M
will exist.
const
pointers
There are two types of const
when it comes to pointers.
- pointers to constants
- constant pointers
Pointers to constants
Pointers that point to data types that are not supposed to be modified are called as pointers to constants.
const type * ptr;
OR
type const * ptr;
Example:
const int K = 10;
const int M = 5;
const int * ptr;
ptr = &K;
// (*ptr)++; // error
ptr = &M; // OK
Even if the data type itself is not const
-qualified, a pointer to constant can still point to it.
int K = 10;
const int * ptr;
ptr = &K;
// (*ptr)++; // error
So using a pointer to constant, one can never modify the referenced data.
Constant pointers
Pointers themselves can also be made constant; in essence, the pointer always points to the same memory location throughout it's lifetime.
type * const ptr = address;
Here, the address the pointer points to is constant, hence the pointer must be initialized at the time of declaration.
Example:
int x = 10;
const int M = 5;
int * const ptr = &x;
(*ptr)++; // OK
// ptr = &M; // error
const
function parameters
Just like constant variables and constant pointers, functions can also have their parameters qualified as const
.
void someFunc(int x, const char c, const char* s, const double d) {
// body
}
someFunc()
takes four parameters. The first one int x
is not const-qualified and hence the value of x
can change inside the function body. The other three parameters are marked as constant. const char c
and const double d
would not allow the values of c
and d
to be changed inside the fucntion scope. const char* s
won't allow the C-string to be modified. But s
can always be assigned a different address.
const
member functions
Member functions can be const-qualified too!
Note: Only member functions can be const
. Non-member functions cannot be const
.
// declaration
return_type function_name (parameter_list) const;
// definition
return_type function_name (parameter_list) const {
// body
}
When a member function is const-qualified, it means that the function guarantees that it will not change the state of this
object when called. As a result, a const-qualified function is not allowed to call a non-const-qualifed fucntion.
Usually, accessors (getters) are const-qualified as they are never supposed to modify the underlying object.
This is a great article, thank you. Up to now it had appeared to me that the key word ‘const’ might appear anywhere in a statement and I was never sure what it was doing.