constinit Spezifizierer (seit C++20)
-
constinit- behauptet, dass eine Variable eine statische Initialisierung hat, d.h. Nullinitialisierung und Konstanteninitialisierung, andernfalls ist das Programm fehlerhaft.
-
Inhalt |
[bearbeiten] Erklärung
Der constinit-Spezifizierer deklariert eine Variable mit statischer oder Thread- Speicherdauer.
|
Der constinit-Spezifizierer kann auch auf strukturelle Bindungen angewendet werden. In diesem Fall wird constinit auch auf die eindeutig benannte Variable angewendet, die durch die Deklaration eingeführt wird. |
(seit C++26) |
Wenn eine Variable mit constinit deklariert wird, muss ihre initialisierende Deklaration mit constinit angewendet werden. Wenn eine mit constinit deklarierte Variable eine dynamische Initialisierung hat (selbst wenn sie als statische Initialisierung durchgeführt wird), ist das Programm fehlerhaft.
Wenn keine constinit-Deklaration an der Stelle der initialisierenden Deklaration erreichbar ist, ist das Programm fehlerhaft, keine Diagnose erforderlich.
constinit kann nicht zusammen mit constexpr verwendet werden. Wenn die deklarierte Variable eine Referenz ist, ist constinit äquivalent zu constexpr. Wenn die deklarierte Variable ein Objekt ist, erzwingt constexpr, dass das Objekt eine statische Initialisierung und eine konstante Zerstörung haben muss und das Objekt als const-qualifiziert macht. constinit erzwingt jedoch keine konstante Zerstörung und keine const-Qualifikation. Infolgedessen kann ein Objekt eines Typs, das konstante Konstruktoren und keinen konstanten Destruktor hat (z. B. std::shared_ptr<T>), mit constinit, aber nicht mit constexpr deklariert werden.
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); // error
constinit kann auch in einer nicht-initialisierenden Deklaration verwendet werden, um dem Compiler mitzuteilen, dass eine thread_local Variable bereits initialisiert ist, wodurch der Aufwand reduziert wird, der andernfalls durch eine versteckte Guard-Variable verursacht würde.
extern thread_local constinit int x; int f() { return x; } // no check of a guard variable needed
[bearbeiten] Hinweise
| Feature-Testmakro | Wert | Std | Feature |
|---|---|---|---|
__cpp_constinit |
201907L |
(C++20) | constinit
|
[bearbeiten] Schlüsselwörter
[bearbeiten] Beispiel
#include <cassert> constexpr int square(int i) { return i * i; } int twice(int i) { return i + i; } constinit int 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 constinit int pow = square(4); // constinit int prev = pow; // Error: constinit can only be applied to a // variable with static or thread storage duration int prev = pow; pow = pow * pow; return prev; } int main() { assert(sq == 4); sq = twice(1); // Unlike constexpr this value can be changed later at runtime assert(sq == 2); assert(square_4_gen() == 16); assert(square_4_gen() == 256); assert(square_4_gen() == 65536); }
[bearbeiten] Fehlerberichte
Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | angewendet auf | Verhalten wie veröffentlicht | Korrigiertes Verhalten |
|---|---|---|---|
| CWG 2543 | C++20 | war das Verhalten unklar, wenn die mit constinit deklarierte Variable dynamisch als Teil der statischen Initialisierung initialisiert wird |
das Programm ist schlecht ge- formt in diesem Fall |
[bearbeiten] Siehe auch
consteval-Spezifizierer(C++20) |
gibt an, dass eine Funktion eine unmittelbare Funktion ist, d. h., jeder Aufruf der Funktion muss in einer konstanten Auswertung erfolgen |
constexpr-Spezifizierer(C++11) |
gibt an, dass der Wert einer Variablen oder Funktion zur Kompilierzeit berechnet werden kann |
| Konstanter Ausdruck | definiert einen Ausdruck, der zur Kompilierzeit ausgewertet werden kann |
| Konstante Initialisierung | setzt die Anfangswerte der statischen Variablen auf eine zur Kompilierzeit konstante. |
| Nullinitialisierung | setzt den Anfangswert eines Objekts auf Null. |