constinit
specifier
(since C++20)
-
-
constinit- stellt sicher, dass eine Variable eine statische Initialisierung hat, d.h. Nullinitialisierung und konstante Initialisierung , andernfalls ist das Programm fehlerhaft.
-
Inhaltsverzeichnis |
Erklärung
Der constinit -Spezifizierer deklariert eine Variable mit statischer oder Thread- Speicherdauer .
|
Der constinit -Spezifizierer kann auch auf strukturierte Bindungen angewendet werden. In diesem Fall wird constinit ebenfalls auf die durch die Deklaration eingeführte eindeutig benannte Variable angewendet. |
(seit C++26) |
Wenn eine Variable mit constinit deklariert wird, muss ihre initialisierende Deklaration mit constinit versehen werden. Wenn eine mit constinit deklarierte Variable eine dynamische Initialisierung aufweist (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, entspricht constinit constexpr . Wenn die deklarierte Variable ein Objekt ist, erfordert constexpr , dass das Objekt statische Initialisierung und konstante Destruktion haben muss und qualifiziert das Objekt als const, während constinit weder konstante Destruktion noch Const-Qualifizierung erfordert. Daher kann ein Objekt eines Typs mit constexpr-Konstruktoren, aber ohne constexpr-Destruktor (z.B. std:: shared_ptr < T > ) mit constinit deklariert werden, aber nicht mit constexpr .
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); // Fehler
constinit kann auch in einer nicht-initialisierenden Deklaration verwendet werden, um dem Compiler mitzuteilen, dass eine thread_local Variable bereits initialisiert ist, wodurch Overhead reduziert wird , der sonst durch eine versteckte Guard-Variable entstehen würde.
extern thread_local constinit int x; int f() { return x; } // keine Überprüfung einer Guard-Variable erforderlich
Hinweise
| Feature-Test-Makro | Wert | Std | Feature |
|---|---|---|---|
__cpp_constinit
|
201907L
|
(C++20) | constinit |
Schlüsselwörter
Beispiel
#include <cassert> constexpr int square(int i) { return i * i; } int twice(int i) { return i + i; } constinit int sq = square(2); // OK: Initialisierung erfolgt zur Compile-Zeit // constinit int x_x = twice(2); // Fehler: Compile-Zeit-Initialisierer erforderlich int square_4_gen() { static constinit int pow = square(4); // constinit int prev = pow; // Fehler: constinit kann nur auf eine // Variable mit statischer oder Thread-Speicherdauer angewendet werden int prev = pow; pow = pow * pow; return prev; } int main() { assert(sq == 4); sq = twice(1); // Im Gegensatz zu constexpr kann dieser Wert später zur Laufzeit geändert werden assert(sq == 2); assert(square_4_gen() == 16); assert(square_4_gen() == 256); assert(square_4_gen() == 65536); }
Fehlerberichte
Die folgenden verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.
| DR | Angewendet auf | Verhalten wie veröffentlicht | Korrektes Verhalten |
|---|---|---|---|
| CWG 2543 | C++20 |
das Verhalten war unklar, wenn die mit
constinit
deklarierte Variable als Teil der statischen Initialisierung dynamisch initialisiert wird |
das Programm ist in diesem Fall fehler-
haft |
Siehe auch
consteval
Spezifizierer
(C++20)
|
spezifiziert, dass eine Funktion eine Immediate-Funktion ist, d.h. jeder Aufruf der Funktion muss in einer Konstantenauswertung erfolgen |
constexpr
Spezifizierer
(C++11)
|
spezifiziert, dass der Wert einer Variable oder Funktion zur Kompilierzeit berechnet werden kann |
| konstanter Ausdruck | definiert einen Ausdruck , der zur Kompilierzeit ausgewertet werden kann |
| konstante Initialisierung | setzt die Anfangswerte der static Variablen auf einen Kompilierzeit-Konstanten |
| Null-Initialisierung | setzt den Anfangswert eines Objekts auf Null |