π§ C++ Cheatsheet: constexpr vs const vs constinit
| Feature | const |
constexpr |
constinit |
|---|---|---|---|
| Mutability | β No | β No | β Yes |
| Compile-time evaluation | β Not guaranteed | β Always | β Initialization only |
| Where it can be used | Anywhere | Anywhere (with restrictions) | Global or static variables only |
Usable in static_assert |
β No | β Yes | β No |
| Avoids runtime initialization | β No | β Yes | β Yes |
| Usable in templates | β No | β Yes | β No |
- Declares an immutable value
- May be initialized at runtime
- Not necessarily known at compile time
const int a = runtime_func(); // OK
a = 10; // β Error: const- Value is guaranteed to be evaluated at compile time
- Variable is immutable
- Can be used in
static_assert, templates, array sizes, etc.
constexpr int square(int x) { return x * x; }
constexpr int a = square(5);
static_assert(a == 25);
int arr[a]; // OK- Declares that a variable will be initialized at compile time
- Value can be mutable
- Only valid for global or
staticvariables - Prevents the "static initialization order fiasco"
constinit int counter = 0;
counter = 42; // OK β not const
constinit int invalid; // β Error: must be initialized
// β Invalid inside functions:
void foo() {
constinit int local = 1; // Error
}// A.cpp
Logger loggerA("A");
// B.cpp
extern Logger loggerA;
Logger loggerB("B", &loggerA); // might use an uninitialized loggerAπ Solution:
- Use
constinit - Or use a function-local
staticvariable:
Logger& getLogger() {
static Logger instance("A"); // lazy and safe
return instance;
}| You need... | Use |
|---|---|
| A constant value known to the compiler | constexpr |
| An immutable value, not necessarily compile-time | const |
| A mutable value initialized at compile-time | constinit |