Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is `constinit` in C++20?

constinit is a new keyword and specifier in C++20 which was proposed in P1143.

The following example is provided in the standard:

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);    // ill-formed 

A few questions come to mind:

  • What does constinit mean? Why was it introduced? In which cases should we use it?

  • Does it make a variable immutable? Does it imply const or constexpr?

  • Can a variable be both const and constinit? What about constexpr and constinit?

  • To which variables can the specifier be applied? Why cannot we apply it to non-static, non-thread_local variables?

  • Does it have any performance advantages?

This question is intended to be used as a reference for upcoming questions about constinit in general.

like image 319
Acorn Avatar asked Sep 08 '19 19:09

Acorn


People also ask

What is Constinit?

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

Why use consteval?

C++20 introduces the keyword consteval, which is used to indicate that a function must evaluate at compile-time, otherwise a compile error will result. Such functions are called immediate functions. In the above example, the first two calls to greater() will evaluate at compile-time.

When to use consteval vs constexpr?

A consteval function can only invoke a constexpr function but not the other way around. use fundamental data types as variables that have to be initialized with a constant expression. A consteval (constexpr) function cannot. have static or thread_local data.

What is consteval in c++?

The consteval specifier declares a function or function template to be an immediate function, that is, every potentially evaluated call (i.e. call out of an unevaluated context) to the function must (directly or indirectly) produce a compile time constant expression.


1 Answers

  • What does constinit mean? Why was it introduced? In which cases should we use it?

Initializing a variable with static storage duration might result in two outcomes¹:

  1. The variable is initialized at compile-time (constant-initialization);

  2. The variable is initialized the first time control passes through its declaration.

Case (2) is problematic because it can lead to the static initialization order fiasco, which is a source of dangerous bugs related to global objects.

The constinit keyword can only be applied on variables with static storage duration. If the decorated variable is not initialized at compile-time, the program is ill-formed (i.e. does not compile).

Using constinit ensures that the variable is initialized at compile-time, and that the static initialization order fiasco cannot take place.


  • Does it make a variable immutable? Does it imply const or constexpr?

No and no.

However, constexpr does imply constinit.


  • Can a variable be both const and constinit? What about constexpr and constinit?

It can be both const and constinit. It cannot be both constexpr and constinit. From the wording:

At most one of the constexpr, consteval, and constinit keywords shall appear in a decl-specifier-seq.

constexpr is not equivalent to const constinit, as the former mandates constant destruction, while the latter doesn't.


  • To which variables can the specifier be applied? Why cannot we apply it to non-static, non-thread_local variables?

It can only be applied to variables with static or thread storage duration. It does not make sense to apply it to other variables, as constinit is all about static initialization.


  • Does it have any performance advantages?

No. However, a collateral benefit of initializing a variable at compile-time is that it doesn't take instructions to initialize during program execution. constinit helps developers ensure that is the case without having to guess or check the generated assembly.


¹: See https://en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables

like image 124
Vittorio Romeo Avatar answered Oct 02 '22 08:10

Vittorio Romeo