[edit]Explanation
Theconstinit specifier declares a variable with static or threadstorage duration.
If a variable is declared withconstinit, itsinitializing declaration must be applied withconstinit. If a variable declared withconstinit hasdynamic initialization (even if it isperformed as static initialization), the program is ill-formed.
If noconstinit declaration is reachable at the point of the initializing declaration, the program is ill-formed, no diagnostic required.
constinit cannot be used together withconstexpr. When the declared variable is a reference,constinit is equivalent toconstexpr. 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 withconstinit but notconstexpr.
constchar* g(){return"dynamic initialization";}constexprconstchar* f(bool p){return p?"constant initializer": g();} constinitconstchar* 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 athread_local variable is already initialized,reducing overhead that would otherwise be incurred by a hidden guard variable.
extern thread_local constinitint x;int f(){return x;}// no check of a guard variable needed
[edit]Keywords
constinit
[edit]Example
#include <cassert> constexprint square(int i){return i* i;} int twice(int i){return i+ i;} constinitint 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 constinitint pow= square(4); // constinit int prev = pow; // Error: constinit can only be applied to a// variable with static or thread storage durationint prev= pow; pow= pow* pow;return prev;} int main(){assert(sq==4); sq= twice(1);// Unlike constexpr this value can be changed later at runtimeassert(sq==2); assert(square_4_gen()==16);assert(square_4_gen()==256);assert(square_4_gen()==65536);}
[edit]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 withconstinit is dynamically initialized as part of static initialization | the program is ill- formed in this case |
[edit]See also