Специфікатор consexpr. Відмінності специфікатора constexpr від const. Приклади
Пошук на інших ресурсах:
Зміст
- 1. Специфікатор constexpr. Застосування для констант. Приклад
- 2. Відмінності між специфікаторами constexpr та const
- 3. Специфікатор constexpr. Застосування для констант. Приклад
- 4. Специфікатор constexpr. Застосування для функцій, які повертають константу. Приклад
- 5. Оголошення констант constexpr на основі інших констант та літералів. Приклад
- Споріднені теми
1. Специфікатор constexpr. Застосування для констант. Приклад
Специфікатор constexpr може застосовуватись:
- для змінних, які потрібно оголосити як константи (для констант);
- для функцій.
Загальна форма оголошення константи з специфікатором constexpr має вигляд
constexpr type ConstantName = value_or_expression;
тут
- type – тип константи;
- ConstantName – ім’я константи;
- value_or_expression – значення (літерал) або вираз. У виразі може викликатись функція, яка позначена також як constexpr.
У випадку визначення для змінних-констант, цей специфікатор задає константи так само як і специфікатор const. Однак, значення цих констант повинні бути визначені одразу на етапі компіляції, а не сформовані пізніше на етапі виконання. Такими значеннями, які визначені одразу є літерали (2.88, “Hello, world!”, true).
Загальна форма оголошення функції з специфікатором constexpr наступна
constexpr return_type FuncName(list_of_parameters) { // ... return const_expr_value; }
тут
- FuncName – ім’я функції, яка повертає константу;
- list_of_parameters – список параметрів функції;
- const_expr_value – значення, яке може обчислюватись на етапі компіляції. Це може бути результат виклику інших constexpr-функцій, значення літералів, значення інших констант, оголошених з специфікатором constexpr.
⇑
2. Відмінності між специфікаторами constexpr та const
Між специфікаторами const та constexpr є наступні відмінності:
1. Ініціалізація змінної const може бути відкладена до часу виконання:
// Тут sqrt() обчислюється пізніше, при виконанні програми const double rc1 = sqrt(4.44 + c1); cout << rc1 << endl;
2. Ініціалізація змінної constexpr не може бути відкладена до часу виконання:
double ce1 = 23.2; constexpr double rce1 = sqrt(2.88); // не працює, оскільки sqrt() обчислиться пізніше
3. Ініціалізацію змінної constexpr можна обчислювати на основі іншої змінної, яка також оголошена як constexpr
// 1. Ініціалізація константи constexpr на основі іншої константи constexpr constexpr int ce1 = 50; constexpr int ce2 = ce1 * 2 + 100; // ce2 = 200 - працює
також на основі константи, яка оголошена як const
// Спроба ініціалізації константи constexpr // на основі іншої константи, оголошеної як const const int c1 = 200; constexpr int ce3 = c1 + 10; // працює, оскільки значення c1 відомо на етапі компіляції
4. Константу типу const можна оголошувати на основі змінної, а константу типу constexpr неможна
// Спроба ініціалізації константи const на основі змінної int v1 = 100; const int c2 = v1 * 3; // працює // Спроба ініціалізації константи constexpr на основі змінної int v2 = 100; constexpr int ce4 = v2 * 3; // помилка, щоб виправити це потрібно v2 оголосити як constexpr
⇑
3. Специфікатор constexpr. Застосування для констант. Приклад
// Змінні constexpr допускається ініціалізовувати значенням літералу, // оскільки значення літералу одразу визначене constexpr double d = true; constexpr double t{ 3.05 }; cout << d << endl; // constexpr float x = exp(2.8); // помилка const float x = exp(2.8); // працює double f = 0.0; //constexpr double v = f + 2.5; // помилка, f не є constexpr // Ініціалізація змінної const може бути відкладена до часу виконання. // 1. Для констант (const) це все працює double c1 = 23.2; // Тут sqrt() обчислюється пізніше, при виконанні програми const double rc1 = sqrt(4.44 + c1); cout << rc1 << endl; // 2. Для констант constexpr це не працює, // тобто ініціалізаці змінної constexpr не може // бути відкладена до часу виконання. // Ця ініціалізація повинна виконуватись одразу, // інакше компілятор видасть помилку. double ce1 = 23.2; constexpr double rce1 = sqrt(2.88); // не працює, оскільки sqrt() обчислиться пізніше constexpr double rce2 = sqrt(ce1); // не працює constexpr double ce2 = 3.8; constexpr double rce3 = sqrt(ce2); // не працює
⇑
4. Специфікатор constexpr. Застосування для функцій, які повертають константу. Приклад
Приклад.
#include <iostream> using namespace std; // Для змінних constexpr і const обов'язково повинен бути ініціалізатор. // Функція, яка повертає число 10 int GetNumber10() { return 10; } // Інша функція, яка повертає 20 constexpr int GetNumber20() { return 20; } void TestVariable() { // Ініціалізація змінної const може бути відкладена до часу виконання. // 1. Для констант (const) це все працює double c1 = 23.2; // Тут sqrt() обчислюється пізніше, при виконанні програми. const double rc1 = sqrt(4.44 + c1); cout << rc1 << endl; // 2. Для констант constexpr це не працює, тобто ініціалізаці змінної constexpr не може бути відкладена до часу виконання. // Ця ініціалізація повинна виконуватись одразу, інакше компілятор видасть помилку. double ce1 = 23.2; //constexpr double rce1 = sqrt(2.88); // не працює, оскільки sqrt() обчислиться пізніше //constexpr double rce2 = sqrt(ce1); // не працює constexpr double ce2 = 3.8; //constexpr double rce3 = sqrt(ce2); // не працює } void main() { // Виклик функції // 1. Специфікатор const // Тут працює, оскільки значення буде отримане на етапі виконання. const int c1 = GetNumber10(); // Тут також працює, але з попередженням помітити c2 як constexpr const int c2 = GetNumber20(); cout << c2; // 2. Специфікатор cosnexpr // Не працює, оскільки constexpr-значення повинно отримуватись на етапі компіляції а не на етапі виконання // constexpr int ce1 = GetNumber10(); // Працює, оскільки функція GetNumber20() помічена як така, що її виклик і // повернення значення повинні виконуватись на етапі компіляції constexpr int ce2 = GetNumber20(); cout << ce2 << endl; }
⇑
5. Оголошення констант constexpr на основі інших констант та літералів. Приклад
// 1. Ініціалізація константи constexpr на основі іншої константи constexpr constexpr int ce1 = 50; constexpr int ce2 = ce1 * 2 + 100; // ce2 = 200 - працює // 2. Спроба ініціалізації константи constexpr на основі іншої константи, оголошеної як const const int c1 = 200; constexpr int ce3 = c1 + 10; // працює, оскільки значення c1 відомо на етапі компіляції // 3. Спроба ініціалізації константи const на основі змінної int v1 = 100; const int c2 = v1 * 3; // працює // 4. Спроба ініціалізації константи constexpr на основі змінної int v2 = 100; constexpr int ce4 = v2 * 3; // помилка, щоб виправити це потрібно v2 оголосити як constexpr
⇑
6. Приклад виклику з constexpr-функції іншої constexpr-функції. Ланцюжок викликів
#include <iostream> using namespace std; // Функція, яка повертає число 15 constexpr int GetNumber15() { return 15; } // Інша constexpr-функція, яка повертає 20. // Ця функція звертається до функції GetNumber15() constexpr int GetNumber20() { return 5 + GetNumber15(); } void main() { // 1. Ініціалізація константи constexpr на основі іншої константи constexpr constexpr int ce1 = 50; constexpr int ce2 = ce1 * 2 + 100; // ce2 = 200 - працює // 2. Спроба ініціалізації константи constexpr на основі іншої константи, оголошеної як const const int c1 = 200; constexpr int ce3 = c1 + 10; // працює, оскільки значення c1 відомо на етапі компіляції // 3. Спроба ініціалізації константи const на основі змінної int v1 = 100; const int c2 = v1 * 3; // працює // 4. Спроба ініціалізації константи constexpr на основі змінної int v2 = 100; //constexpr int ce4 = v2 * 3; // помилка, щоб виправити це потрібно v2 оголосити як constexpr // Виклик функції GetNumber20() для ініціалізації constexpr-константи з іменем d1 constexpr double d1 = GetNumber20(); // 20 - працює cout << d1 << endl; }
⇑
Споріднені теми
- Поняття змінної. Оголошення змінної. Операція розширення області видимості :: . Виділення пам’яті для змінної. Константи
- Поняття виразу. Операція присвоєння. Перетворення та приведення типів. Ініціалізація. Уніфікована ініціалізація
⇑