const и constexpr
Некоторые значения программа задаёт один раз и больше не меняет: число попыток, длину суток в секундах, курс валюты на момент запуска. Если объявить такую переменную с const, случайно изменить её не даст компилятор:
int main() {
const int max_tries = 3;
max_tries = 5; // ✗
}error: cannot assign to variable 'max_tries' with const-qualified type 'const int'Это ошибка компиляции, а не предупреждение: программа не соберётся, пока лишнее присваивание не уберут.
Только для чтения
const перед типом запрещает менять переменную после инициализации. Поэтому начальное значение у неё обязательно: const int max_tries; тоже не скомпилируется. Само значение может быть любым, в том числе вычисленным во время работы программы:
#include <iostream>
int main() {
int width = 4;
const int area = width * width;
width = 5;
std::cout << area << ' ' << width << '\n'; // 16 5
}area получила значение при инициализации и сохранила его, когда изменилась width. const относится к переменной, а не к значению. Копия const-переменной — обычная переменная, и её можно менять. Читателю const тоже помогает: значение такой переменной задано в одном месте — в объявлении.
Значение при компиляции
constexpr требует большего: значение должно быть известно уже при компиляции. Поэтому такую переменную инициализируют константой — например, литералом или выражением из литералов и других constexpr-переменных. const-переменная со значением, вычисленным во время работы программы, как area выше, для этого не подходит. Компилятор вычисляет такое выражение сам, и программа получает готовое число:
#include <iostream>
int main() {
constexpr int kSecondsPerHour = 60 * 60;
constexpr int kSecondsPerDay = 24 * kSecondsPerHour;
std::cout << kSecondsPerDay << '\n'; // 86400
}Изменить constexpr-переменную тоже нельзя: constexpr включает в себя const. Если значение известно заранее, объявляйте переменную constexpr, а если оно появляется только во время работы — const. Имена constexpr-констант в курсе пишут в стиле kName, а const-переменные называют как обычные.
Частая ошибка
constexpr-переменную инициализируют значением, которое известно только во время работы программы:
int main() {
int width = 4;
constexpr int area = width * width; // ✗
return area;
}error: constexpr variable 'area' must be initialized by a constant expressionwidth — обычная переменная: число 4 записано прямо в коде, но переменную можно изменить, поэтому константой её значение не считается. Объявите area как const: ей хватит значения, вычисленного во время работы. Другой способ — сделать constexpr и саму width: тогда width * width известно уже при компиляции.