#новичкам
Когда мы определяем константу в скоупе функции у нас есть несколько вариантов, как это сделать: пометить const, constexpr, const static, constexpr static. Какой вариант выбрать?
Идентификатор constexpr говорит о том, что значение переменной обязательно должно быть известно во время компиляции. Просто const перед локальной переменной такого не требует, это обычная константа времени выполнения. Ну а static в этом контекcте продлевает время жизни переменной до конца работы программы.
Особенности функционала диктуют кейсы применения.
1️⃣ Если константа зависит от входных данных функции, то ее нужно помечать, как const. constexpr здесь по определению не подойдет, не-consteval функции могут выполняться в рантайме, а в consteval функциях входные параметры не считаются за constexpr. static тоже, потому что один раз определив статическую константу, вы ее не сможете поменять.
std::pair<double, double> normalizeVector(double x, double y) {
const double LENGTH = std::sqrt(x * x + y * y); // Зависит от x и y
return {x / LENGTH, y / LENGTH};
}2️⃣ Если константа не зависит от входных данных функции и она известна во время компиляции, то лучше ее определить, как constexpr static. Тогда такая локальная переменная гарантированно не будет занимать пространство на стеке при каждом вызове функции, ее инициализация точно пройдет в compile-time и об этом будет явно сказано в коде программы.
double metersToMiles(double meters) {
constexpr static double METERS_IN_MILE = 1609.34;
return meters / METERS_IN_MILE;
}Вообще этот пост в принципе родился из вопроса: "как помечать локальные константы, значения которых известны на этапе компиляции?". В большинстве случаев можно пометить константу просто constexpr, компилятор скорее всего ее оптимизирует и вставит ее значение в места вызовов, но это не гарантируется. Например, если вы по каким-то причинам будете использовать адрес этой локальной константы, то компилятор будет вынужден класть ее на стек на каждом вызове.
Зачем делать ненужные действия? Если значение переменной не меняется от вызова к вызову, то она больше подходит на глобальную константу. А чтобы не засорять глобальный скоуп переменной, которая используется только в этой функции, то можно сделать ее статической локальной переменной и получить тот же результат.
Be expressive. Stay cool