Spec-Zone.ru › C++

constinit specifier (since C++20)

  • constinit - asserts that a variable has static initialization, i.e. zero initialization and constant initialization, otherwise the program is ill-formed.

Explanation

The constinit specifier declares a variable with static or thread storage duration.

The constinit specifier can also be applied to structured binding declarations. In this case, constinit is also applied to the uniquely-named variable introduced by the declaration.

(since C++26)

If a variable is declared with constinit, its initializing declaration must be applied with constinit. If a variable declared with constinit has dynamic initialization (even if it is performed as static initialization), the program is ill-formed.

If no constinit declaration is reachable at the point of the initializing declaration, the program is ill-formed, no diagnostic required.

constinit cannot be used together with constexpr. When the declared variable is a reference, constinit is equivalent to constexpr. When the declared variable is an object, constexpr mandates that the object must have static initialization and constant destruction and makes the object const-qualified, however, constinit does not mandate constant destruction and const-qualification. As a result, an object of a type which has constexpr constructors and no constexpr destructor (e.g. std::shared_ptr<T>) might be declared with constinit but not 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 can also be used in a non-initializing declaration to tell the compiler that a thread_local variable is already initialized, reducing overhead that would otherwise be incurred by a hidden guard variable.

extern thread_local constinit int x;
int f() { return x; } // no check of a guard variable needed

Notes

Feature-test macro Value Std Feature
__cpp_constinit 201907L (C++20) constinit

Keywords

constinit

Example

#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);
}

Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards.

DR Applied to Behavior as published Correct behavior
CWG 2543 C++20 the behavior was unclear if the variable declared with constinit
is dynamically initialized as part of static initialization
the program is ill-
formed in this case

See also

consteval specifier(C++20) specifies that a function is an immediate function, that is, every call to the function must be in a constant evaluation
constexpr specifier(C++11) specifies that the value of a variable or function can be computed at compile time
constant expression defines an expression that can be evaluated at compile time
constant initialization sets the initial values of the static variables to a compile-time constant
zero initialization sets the initial value of an object to zero

© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/language/constinit

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API