Ch7.5: constinit
Overview
constinit guarantees that a variable is initialized at compile
time, but unlike constexpr, the variable itself does not need
to be a constant expression. It simply ensures that the initialization
happens before any dynamic initialization.
This is extremely useful for preventing static initialization order problems.
1. Basic example
A constinit variable must be initialized with a constant
initializer, but the variable itself does not need to be constexpr.
#include
constinit int counter = 0; // guaranteed compile-time initialization
int main()
{
using namespace ::fast_io::iomnp;
++counter; // OK: not constexpr
print("counter = ", counter, "\n");
}
The initialization is compile‑time, but the variable is mutable at runtime.
2. Why this is useful
constinit solves a real problem: the static initialization
order fiasco. It ensures that a global variable is initialized before any
dynamic initialization begins.
Without constinit, two global variables in different
translation units may be initialized in an unpredictable order.
3. Preventing static initialization order issues
Consider two global variables in different files:
// file A
#include
constinit int global_value = 42;
// file B
extern int global_value;
int compute()
{
return global_value * 2; // safe: global_value is initialized early
}
Because global_value is constinit, it is
guaranteed to be initialized before compute() runs.
4. Difference from constexpr
constexpr means:
- the value must be a constant expression
- the variable cannot be modified
constinit means:
- the variable must be initialized at compile time
- the variable can be modified at runtime
- the value does not need to be a constant expression
constexpr int a = 5; // constant expression, immutable
constinit int b = 5; // compile-time init, mutable
b can be changed at runtime; a cannot.
5. constinit does not force constant evaluation
constinit only requires that the initializer is a constant
initializer. It does not force the variable to be used in constant
expressions.
constinit int x = 10; // must be initialized at compile time
int y = x + 5; // runtime use is fine
This makes constinit ideal for global state that must be
initialized early but remains mutable.
Key takeaways
constinitguarantees compile‑time initialization.- The variable itself may be modified at runtime.
- It prevents static initialization order problems.
- It is different from
constexpr, which requires constant expressions. - It is ideal for global variables that must be initialized early.