Namespaces
Variants

constinit specifier (since C++20)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous
  • 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

Ключевые слова

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) указывает, что значение переменной или функции может быть вычислено во время компиляции
константное выражение определяет выражение , которое может быть вычислено во время компиляции
константная инициализация устанавливает начальные значения статических переменных в константу времени компиляции
нулевая инициализация устанавливает начальное значение объекта в ноль