constinit
specifier
(since C++20)
-
-
constinit- утверждает, что переменная имеет статическую инициализацию, т.е. zero initialization и constant initialization , иначе программа является некорректной.
-
Содержание |
Объяснение
Спецификатор constinit объявляет переменную со статической или поточной продолжительностью хранения .
|
Спецификатор constinit также может применяться к объявлениям структурированных привязок . В этом случае constinit также применяется к уникально именованной переменной , вводимой объявлением. |
(начиная с C++26) |
Если переменная объявлена с constinit , её инициализирующее объявление должно быть помечено constinit . Если переменная, объявленная с constinit , имеет динамическую инициализацию (даже если она выполняется как статическая инициализация ), программа является некорректной.
Если объявление constinit недоступно в точке инициализирующего объявления, программа является некорректной, диагностика не требуется.
constinit нельзя использовать вместе с constexpr . Когда объявленная переменная является ссылкой, constinit эквивалентен constexpr . Когда объявленная переменная является объектом, constexpr требует, чтобы объект имел статическую инициализацию и постоянное уничтожение, а также делает объект константно-квалифицированным, однако constinit не требует постоянного уничтожения и константной квалификации. В результате объект типа, который имеет constexpr-конструкторы, но не имеет constexpr-деструктора (например, std:: shared_ptr < T > ), может быть объявлен с constinit , но не с constexpr .
const char* g() { return "dynamic initialization"; } constexpr const char* f(bool p) { return p ? "constant initializer" : g(); } constinit const char* c = f(true); // OK // constinit const char* d = f(false); // ошибка
constinit также может использоваться в неинициализирующем объявлении, чтобы сообщить компилятору, что thread_local переменная уже инициализирована, снижая издержки , которые в противном случае были бы вызваны скрытой переменной-стражем.
extern thread_local constinit int x; int f() { return x; } // проверка переменной-сторожа не требуется
Примечания
| Макрос тестирования возможностей | Значение | Стандарт | Возможность |
|---|---|---|---|
__cpp_constinit
|
201907L
|
(C++20) | constinit |
Ключевые слова
Пример
#include <cassert> constexpr int square(int i) { return i * i; } int twice(int i) { return i + i; } constinit int sq = square(2); // OK: инициализация выполняется во время компиляции // constinit int x_x = twice(2); // Ошибка: требуется инициализатор времени компиляции int square_4_gen() { static constinit int pow = square(4); // constinit int prev = pow; // Ошибка: constinit может применяться только к // переменной со статической или потоковой длительностью хранения int prev = pow; pow = pow * pow; return prev; } int main() { assert(sq == 4); sq = twice(1); // В отличие от constexpr это значение может быть изменено позже во время выполнения assert(sq == 2); assert(square_4_gen() == 16); assert(square_4_gen() == 256); assert(square_4_gen() == 65536); }
Отчеты о дефектах
Следующие отчеты об изменениях поведения, влияющие на дефекты, были применены задним числом к ранее опубликованным стандартам C++.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| CWG 2543 | C++20 |
поведение было неясным, если переменная, объявленная с
constinit
динамически инициализируется как часть статической инициализации |
программа является некорректно
сформированной в этом случае |
Смотрите также
consteval
спецификатор
(C++20)
|
указывает, что функция является немедленной функцией , то есть каждый вызов функции должен быть в константном вычислении |
constexpr
спецификатор
(C++11)
|
указывает, что значение переменной или функции может быть вычислено во время компиляции |
| константное выражение | определяет выражение , которое может быть вычислено во время компиляции |
| константная инициализация | устанавливает начальные значения статических переменных в константу времени компиляции |
| нулевая инициализация | устанавливает начальное значение объекта в ноль |