Ответ
constexpr указывает, что значение переменной или функция могут быть вычислены на этапе компиляции, что позволяет использовать их в контекстах, требующих константных выражений.
Основные применения:
- Константы времени компиляции:
constexpr int SIZE = 100; // Константа времени компиляции int arr[SIZE]; // OK - размер массива известен при компиляции
// Без constexpr было бы: // const int runtime_size = getSize(); // Вычисляется в runtime // int arr2[runtime_size]; // Ошибка: размер массива должен быть константой
2. **Функции, вычисляемые при компиляции:**
```cpp
constexpr int factorial(int n) {
return (n <= 1) ? 1 : n * factorial(n - 1);
}
int main() {
constexpr int fact5 = factorial(5); // Вычисляется при компиляции: 120
int arr[fact5]; // OK - размер 120
int x = 10;
int runtime_fact = factorial(x); // Вычисляется в runtime, если x не constexpr
}
- Шаблоны и метапрограммирование:
// С C++17 constexpr if constexpr bool is_power_of_two(int n) { if constexpr (sizeof(int) == 4) { return n > 0 && (n & (n - 1)) == 0; } else { // Адаптация под другие размеры int return false; } }
Отличие от const:
const- "не изменяемый после инициализации", может вычисляться в runtimeconstexpr- гарантированно вычисляется при компиляции (если аргументы известны)
Эволюция в стандартах:
- C++11: базовые constexpr функции
- C++14: больше возможностей в constexpr функциях
- C++17: constexpr if, лямбды
- C++20: constexpr виртуальные функции, динамическое выделение памяти в constexpr
Ответ 18+ 🔞
Ну слушай, вот есть у нас эта штука constexpr, и она, блядь, реально меняет правила игры. Представь себе: ты пишешь код, а компилятор уже на этапе компиляции всё вычисляет, как будто он заранее знает ответы на все твои вопросы. Это как списать домашку у отличника до урока — всё готово, и тебе на паре остаётся только кивать.
Короче, на что это всё похоже:
- Константы, которые не подведут:
constexpr int SIZE = 100; // Всё, приехали. Эта сотня вшита в бинарник намертво. int arr[SIZE]; // И массив на 100 элементов — пожалуйста, без вопросов.
// А вот без constexpr был бы пиздец: // const int runtime_size = getSize(); // А эта функция когда выполнится? В рантайме! // int arr2[runtime_size]; // Ошибка! Компилятор охуевает: "Мужик, я откуда знаю, какой размер?"
2. **Функции, которые работают, пока ты спишь:**
```cpp
constexpr int factorial(int n) {
return (n <= 1) ? 1 : n * factorial(n - 1);
}
int main() {
constexpr int fact5 = factorial(5); // Компилятор тут же, не отходя от кассы, умножает 5*4*3*2*1 = 120
int arr[fact5]; // И спокойно создаёт массив на 120 элементов — красота!
int x = 10; // А вот это уже переменная, её значение только в рантайме известно.
int runtime_fact = factorial(x); // Тут уже будет обычный вызов функции, как все привыкли.
}
- Шаблонная магия на стероидах:
// С C++17 появился constexpr if — это вообще песня! constexpr bool is_power_of_two(int n) { if constexpr (sizeof(int) == 4) { // Компилятор смотрит: "Ага, int у нас 4 байта" return n > 0 && (n & (n - 1)) == 0; // Тогда используем этот хитрый трюк с битами. } else { // А если архитектура какая-нибудь левая, то и ветка другая. return false; } }
А теперь главное — не путай с const, а то будет тебе хиросима!
const— это как обещание: "я больше не изменюсь". Но когда это обещание даётся? Может, прямо сейчас, а может, и в рантайме, когда программа уже бежит.constexpr— это ультиматум компилятору: "брат, ты прямо здесь и сейчас всё посчитай и вшей в программу". Гарантия на 100%, что никакого рантайма.
Как это всё росло, как развивалось:
- C++11: только появились, скромные такие, базовые функции.
- C++14: уже расходились, больше возможностей дали.
- C++17: вообще охуели —
constexpr ifи лямбды подтянули. - C++20: тут уже пошла полная пизда — виртуальные функции и динамическая память в
constexpr. Представляешь? Выделение памяти, которое компилятор обрабатывает! Ёперный театр, да?
В общем, constexpr — это мощный инструмент, чтобы выжать из компилятора всё, на что он способен. Используй, и будет тебе счастье, а не просто код, который жрёт ресурсы как не в себя.