Namensräume
Varianten
Aktionen

constinit Spezifizierer (seit C++20)

Von cppreference.com
< cpp‎ | Sprache
 
 
C++ Sprache
Allgemeine Themen
Kontrollfluss
Bedingte Ausführungsaussagen
if
Iterationsanweisungen (Schleifen)
for
Bereichs-for (C++11)
Sprunganweisungen
Funktionen
Funktionsdeklaration
Lambda-Funktionsausdruck
inline-Spezifizierer
Dynamische Ausnahmespezifikationen (bis C++17*)
noexcept-Spezifizierer (C++11)
Ausnahmen
Namensräume
Typen
Spezifizierer
const/volatile
decltype (C++11)
auto (C++11)
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Speicherdauer-Spezifizierer
Initialisierung
Ausdrücke
Alternative Darstellungen
Literale
Boolesch - Ganzzahl - Gleitkommazahl
Zeichen - String - nullptr (C++11)
Benutzerdefinierte (C++11)
Dienstprogramme
Attribute (C++11)
Typen
typedef-Deklaration
Typalias-Deklaration (C++11)
Umwandlungen
Speicherzuweisung
Klassen
Klassenspezifische Funktionseigenschaften
explicit (C++11)
static

Spezielle Member-Funktionen
Templates
Sonstiges
 
 

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

constinit

[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[bearbeiten]
constexpr-Spezifizierer(C++11) gibt an, dass der Wert einer Variablen oder Funktion zur Kompilierzeit berechnet werden kann[edit]
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.