const and constexpr
Some values are set once and never change: the number of tries, a day's length in seconds, an exchange rate at startup. Such a box is best sealed with tape as soon as the value is in it. If such a value is kept in a const variable, the compiler stops any accidental change to it:
int main() {
const int max_tries = 3;
max_tries = 5; // ✗
}error: cannot assign to variable 'max_tries' with const-qualified type 'const int'This is a compile error, not a warning: the program does not build until the extra assignment is removed.
Read-only variables
const before the type forbids changing the variable after initialization. That is why it must have an initial value: const int max_tries; does not compile either. The value itself can be anything, including one computed while the program runs:
#include <iostream>
int main() {
int width = 4;
const int area = width * width;
width = 5;
std::cout << area << ' ' << width << '\n'; // 16 5
}area got its value at initialization and kept it when width changed. const belongs to the variable, not to the value. A copy of a const variable is an ordinary variable, and it can change: the contents moved to a new box, and that box has no tape. const helps the person who reads the code too: the value of such a variable is set in one place, the declaration.
Values at compile time
If const is a box sealed when it was first packed, constexpr is a box packed and sealed back at the factory. constexpr demands more: the value must be known at compile time. So such a variable is initialized with a constant—for example, a literal or an expression of literals and other constexpr variables. A const variable whose value is computed at run time, like area above, does not qualify. The compiler computes an expression of literals and constexpr variables itself, and the program gets the computed result:
#include <iostream>
int main() {
constexpr int kSecondsPerHour = 60 * 60;
constexpr int kSecondsPerDay = 24 * kSecondsPerHour;
std::cout << kSecondsPerDay << '\n'; // 86400
}A constexpr variable cannot be changed either: constexpr includes const. One rule helps you choose between them:
- the value is known in advance: declare the variable
constexpr; - the value appears only while the program runs: declare it
const.
Interviewers often ask about the difference between const and constexpr. In this course, constexpr constants are named in the kName style, while const variables get ordinary names.
Common mistake
A constexpr variable is initialized with a value that is known only while the program runs:
int main() {
int width = 4;
constexpr int area = width * width; // ✗
return area;
}error: constexpr variable 'area' must be initialized by a constant expressionwidth is an ordinary variable. The 4 is written right in the code, but the variable can change, so its value is not a constant. Declare area as const: a value computed at run time is enough for it. Another way is to make width itself constexpr: then width * width is known at compile time.
Key points
constforbids changing a variable after initialization, and its initial value may be computed at run time.constexprneeds a value known at compile time: a literal or an expression of literals andconstexprvariables.constbelongs to the variable, not to the value: a copy of aconstvariable can change.constexpr int area = width * width;does not compile whenwidthis an ordinary variable.
Subscribe to take the course
The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.