Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что делает ключевое слово constexpr?
constexpr — это ключевое слово в C++, которое сообщает компилятору, что функция или переменная может быть вычислена во время компиляции. Это один из самых мощных инструментов для оптимизации и безопасности типов в современном C++.
Основное значение
constexpr означает две вещи одновременно:
- Значение известно на этапе компиляции (может быть вычислено компилятором)
- Значение неизменяемо (как const)
constexpr переменные
// Обычная const — значение может быть на время выполнения
const int a = std::rand(); // Вычисляется в runtime
// constexpr — должно быть на этапе компиляции
constexpr int b = 10; // OK - вычисляется на этапе компиляции
constexpr int c = std::rand(); // ОШИБКА - std::rand() не constexpr
// constexpr может использоваться как размер массива
constexpr int SIZE = 100;
int arr[SIZE]; // OK - SIZE известно на этапе компиляции
int len = 100;
int arr2[len]; // ОШИБКА - len не известна на этапе компиляции
constexpr функции
Функция может работать как на этапе компиляции, так и во время выполнения:
// Простая constexpr функция
constexpr int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1);
}
// Вычисляется на этапе компиляции
constexpr int fact5 = factorial(5); // 120 (в момент компиляции)
// Вычисляется во время выполнения
int n = 5;
int result = factorial(n); // 120 (в runtime, обычная функция)
// Пример: вычисление на этапе компиляции
int arr[factorial(5)]; // Массив размером 120 - работает!
Ограничения constexpr функций
Функция может быть constexpr только если:
- Состоит из простых операций (арифметика, условия, циклы)
- Не содержит статических переменных
- Не содержит goto и меток
- Все параметры и возвращаемое значение "литеральные" типы (int, double, но не std::string до C++20)
// OK - простая функция
constexpr int add(int a, int b) {
return a + b;
}
// OK - циклы разрешены (C++14)
constexpr int sum(int n) {
int result = 0;
for (int i = 1; i <= n; i++) {
result += i;
}
return result;
}
// ОШИБКА - не может быть constexpr
constexpr std::string greet(std::string name) { // ОШИБКА до C++20
return "Hello, " + name;
}
Примеры использования
Пример 1: Таблица квадратов во время компиляции
constexpr int square(int x) {
return x * x;
}
// Массив инициализируется во время компиляции
const int squares[] = {
square(1), // 1
square(2), // 4
square(3), // 9
square(4), // 16
square(5) // 25
};
// После компиляции это просто: [1, 4, 9, 16, 25]
Пример 2: Константы для шаблонов
constexpr int MAX_BUFFER_SIZE = 1024;
template<int N>
class Buffer {
char data[N]; // N должно быть известно на этапе компиляции
};
Buffer<MAX_BUFFER_SIZE> buf; // OK
int size = 512;
Buffer<size> buf2; // ОШИБКА - size не constexpr
Пример 3: Оптимизация производительности
// Без constexpr - вычисляется каждый раз в runtime
int power(int base, int exp) {
int result = 1;
for (int i = 0; i < exp; i++) {
result *= base;
}
return result;
}
int main() {
int p = power(2, 10); // 1024 операций в runtime
}
// С constexpr - вычисляется один раз на этапе компиляции
constexpr int power(int base, int exp) {
int result = 1;
for (int i = 0; i < exp; i++) {
result *= base;
}
return result;
}
int main() {
constexpr int p = power(2, 10); // Вычислено: p = 1024 (нет кода в бинарнике)
}
constexpr vs const
| Характеристика | const | constexpr |
|---|---|---|
| Может быть вычислено на этапе компиляции | Нет | Да |
| Может быть вычислено во время выполнения | Да | Нет (для constexpr значения) |
| Используется как размер массива | Нет | Да |
| В шаблонах | Нет | Да |
| Синтаксис проще | Да | Нет |
const int a = std::rand(); // OK - вычисляется в runtime
const int b = computeValue(); // OK - вычисляется в runtime
constexpr int c = 10; // OK - известно на этапе компиляции
constexpr int d = factorial(5); // OK - factorial может быть вычислена на этапе компиляции
C++20 и далее
C++20 расширил возможности constexpr:
- constexpr std::string и контейнеры
- constexpr new/delete (правда ограниченно)
- std::is_constant_evaluated() — проверить, выполняется ли код на этапе компиляции
// C++20
constexpr std::string greet() {
return "Hello"; // Теперь работает!
}
Выводы
constexpr — это инструмент для:
- Производительности — вычисление один раз на этапе компиляции
- Безопасности типов — гарантирует, что значение известно заранее
- Zero-cost абстракции — нет затрат во время выполнения
Оно требует дополнительных усилий для написания, но даёт гарантии и оптимизации, которые невозможны с обычным кодом.