constinit спецификатор (начиная с C++20)
-
constinit— утверждает, что переменная имеет статическую инициализацию, то есть инициализацию нулём и константную инициализацию, в противном случае программа некорректна.
Объяснение
Спецификатор 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); // error
constinit также можно использовать в объявлении без инициализации, чтобы сообщить компилятору, что переменная thread_local уже инициализирована, уменьшая накладные расходы, которые в противном случае возникли бы из-за скрытой переменной-защитника.
extern thread_local constinit int x;
int f() { return x; } // no check of a guard variable needed
Примечания
| Макрос проверки поддержки функции | Значение | Стандарт | Функция |
|---|---|---|---|
__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: initialization is done at compile time
// constinit int x_x = twice(2); // Error: compile time initializer required
int square_4_gen()
{
static constinit int pow = square(4);
// constinit int prev = pow; // Error: constinit can only be applied to a
// variable with static or thread storage duration
int prev = pow;
pow = pow * pow;
return prev;
}
int main()
{
assert(sq == 4);
sq = twice(1); // Unlike constexpr this value can be changed later at runtime
assert(sq == 2);
assert(square_4_gen() == 16);
assert(square_4_gen() == 256);
assert(square_4_gen() == 65536);
}
Отчёты об ошибках
Следующие отчёты об ошибках, изменяющие поведение, были ретроактивно применены к ранее опубликованным стандартам C++.
| DR | Применяется к | Опубликованное поведение | Правильное поведение |
|---|---|---|---|
| CWG 2543 | C++20 | поведение было неясным, если переменная, объявленная с constinit, динамически инициализировалась в рамках статической инициализации | в этом случае программа некорректна |
См. также
consteval спецификатор(C++20) | указывает, что функция является непосредственной функцией, то есть каждый вызов функции должен находиться в контексте константного вычисления |
constexpr спецификатор(C++11) | указывает, что значение переменной или функции может быть вычислено во время компиляции |
| константное выражение | определяет выражение, которое может быть вычислено во время компиляции |
| константная инициализация | задаёт начальные значения статических переменных как константы времени компиляции |
| инициализация нулём | задаёт начальное значение объекта равным нулю |
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/constinit