tags:
- Cpp
Constinit in C++ (ENG)
We have discussed constexpr
and consteval
, so in this note, let's delve into the details of constinit
. The constinit
specifier was introduced in C++20 along with consteval
. While consteval
specifies that a function must produce a constant expression at compile-time, it is easy to guess that constinit
is used to ensure a variable must be initialized at compile-time, quite similar to how consteval
applies to functions.
To use constinit
, the approach differs from what we do with consteval
. We mentioned that constexpr
can be used anywhere, but it does not guarantee compile-time function execution. This is where consteval
comes in—it is more strict and provides guaranteed compile-time function evaluation (CTFE) semantics. So, does the constinit
specifier simply provide compile-time initialization to variables compared to constexpr
? Nuh-uh!
The constinit
specifier is only allowed to declare variables with static storage duration(global variable has this static semantics by default) and thread-local variables. This means that regular stack variables(automatic storage duration) cannot be declared as constinit
. Here's some examples:
constinit int globalVar = 100; // Allowed because globalVar has static storage duration
int main() {
constexpr int localVar = 100; // okay
constinit int localVar2 = 100; // Error: localVar has automatic storage
constinit static int staticVar = 100; // okay
return 0;
}
In contrast to static storage duration, we have dynamic storage duration too. Objects with dynamic storage duration are often created and destroyed using the new
and delete
keywords. Since these objects are allocated and deallocated at run-time, you cannot force the compiler to allocate any memory for them at compile-time. Therefore, if you try to declare a variable with dynamic storage duration as constinit
, it will cause you an error.