C++ Constants

A constant is a variable that has a value which cannot be changed once the constant has been assigned. Unlike variables, constants never change in value. You must initialize a constant when it is created. This allows the compiler to enforce that the variable’s value is not changed anywhere in the code by mistake.

Constant Variables

A variable can be made into a constant by adding the const keyword either before or after the data type. The variable becomes read-only once the const modifier added and the value must be assigned at the same time as it is declared. Attempting to change the value anywhere in the program will results in a compile-time error.

Example
snippet
const int var = 5;
int const var2 = 10; // alternative order
Constant Pointers

In pointers, const can be used in two ways.

First, the pointer can be made constant, which means that it cannot be changed to point to another location.

Example #1
snippet
int myPointee;
int* const p = &myPointee; // pointer constant

Second, the pointee can be declared constant. This means that the variable pointed to cannot be modified through this pointer.

Example #2
snippet
const int* q = &var; // pointee constant

It is possible to declare both the pointer and the pointee as constant to make them both read-only.

snippet
const int* const r = &var; // pointer & pointee constant

Note that constant variables may not be pointed to by a non-constant pointer. This prevents programmers from accidentally rewriting a constant variable using a pointer.

snippet
int* s = &var; // error: const to non-const assignment
Constant References

References can be declared constant in the same way as pointers. However, since reseating a reference is never allowed, declaring the reference as const would be redundant. It only makes sense to protect the referee from change.

snippet
const int& y = var; // referee constant
Constant Objects

Just as with variables, pointers and references, objects can also be declared constant. Take the following class as an example.

snippet
class MyClass
{
public: int x;
void setX(int a) { x = a; }
};

A constant object of this class cannot be reassigned to another instance. The constness of an object also affects its fields and prevent them from being changed.

snippet
const MyClass a, b;
a = b; // error: object is const
a.x = 10; // error: object field is const
Constant Methods

Because of this last restriction, a constant object may not call a non-constant method since such methods are allowed to change the object’s fields.

snippet
a.setX(2); // error: cannot call non-const method

They may only call constant methods, which are methods that are marked with the const modifier before the method body.

snippet
int getX() const { return x; } // constant method

This const modifier means that the method is not allowed to modify the state of the object and can therefore safely be called by a constant object of the class. More specifically, the const modifier applies to the this pointer that is implicitly passed to the method. This effectively restricts the method from modifying the object’s fields or calling any non-constant methods in the class.

Constant Return Type and Parameters

In addition to making a method constant, the return type and method parameters may also be made read-only. For example, if a field is returned by reference instead of by value from a constant method it is important that it is returned as a constant in order to maintain the constness of the object. Not all C++ compilers will be able to catch this subtle mistake.

snippet
const int& getX() const { return x; }
Constant Fields

Both static and instance fields in a class can be declared constant. A constant instance field must be assigned its value using the constructor initialization list. This is the same as the preferred way of initializing regular (non-constant, non-static) fields.

snippet
class MyClass {
    public:
        int i;
    const int c;
    MyClass(): c(5), i(5) {}
}

A constant static field has to be defined outside of the class declaration, in the same way as non-constant static fields. The exception to this is when the constant static field is of an integer data type. Such a field may also be initialized within the class at the same time as the field is declared.

snippet
class MyClass
{
public:
static int si;
const static double csd;
const static int csi = 5;
};
int MyClass::si = 1.23;
const double MyClass::csd = 1.23;
Constant Expressions

The keyword constexpr was introduced in C++11 to indicate a constant expression. Like const it can be applied to variables to make them constant, causing a compilation error if any code attempts to modify the value. constexpr int myConst = 5;

snippet
myConst = 3; // error: variable is const
Unlike const variables, which may be assigned at runtime, a constant expression variable will be computed at compile time. Such a variable can therefore always be used where a compile-time constant is needed, such as in an array and enum declarations. Prior to C++11, this was only allowed for constant integer and enumeration types. int myArray[myConst + 1];

Functions and class constructors may also be defined as constant expressions, which is not allowed with const. Using constexpr on a function limits what the function is allowed to do. In short, the function must consist of a single return statement, and it can only reference other constexpr functions and global constexpr variables. C++14 relaxes these constraints, allowing constexpr functions to contain other executable statements.

snippet
constexpr int getDefaultSize(int multiplier)
{
return 3 * multiplier;
}

The return value for a constexpr function is guaranteed to be evaluated at compile time only when its arguments are constant expressions and the return value is used where a compile-time constant is necessary.

snippet
// Compile-time evaluation
int myArray[getDefaultSize(10)];
If the function is called without constant arguments, it returns a value at runtime just
like a regular function.
// Run-time call
int mul = 10;
int size = getDefaultSize(mul);

Constructors can be declared with constexpr, to construct a constant expression object. Such a constructor must be trivial.

snippet
class Circle
{
public:
int r;
constexpr Circle(int x) : r(x) {}
};

When called with a constant expression argument, the result will be a compile-time generated object with read-only fields. With other arguments it will behave as an ordinary constructor.

snippet
// Compile-time object
constexpr Circle c1(5);
// Run-time object
int x = 5;
Circle c2(x);
Constant Guideline

In general, it is a good idea to always declare variables as constants if they do not need to be modified. This ensures that the variables are not changed anywhere in the program by mistake, which in turn will help to prevent bugs. There is also a performance gain by allowing the compiler the opportunity to hard-code constant expressions into the compiled program. This allows the expression to be evaluated only once – during compilation – rather than every time the program runs.

Related Tutorial
Follow Us
https://www.facebook.com/Rookie-Nerd-638990322793530 https://twitter.com/RookieNerdTutor https://plus.google.com/b/117136517396468545840 #
Contents +