Namespaces
Variants

constinit specifier (since C++20)

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

Table des matières

Explication

Le spécificateur constinit déclare une variable avec une durée de stockage statique ou thread.

Le spécificateur constinit peut également être appliqué aux déclarations de liaisons structurées . Dans ce cas, constinit est également appliqué à la variable à nom unique introduite par la déclaration.

(depuis C++26)

Si une variable est déclarée avec constinit , sa déclaration d'initialisation doit être appliquée avec constinit . Si une variable déclarée avec constinit a une initialisation dynamique (même si elle est exécutée comme initialisation statique ), le programme est mal formé.

Si aucune déclaration constinit n'est accessible au point de la déclaration d'initialisation, le programme est mal formé, aucun diagnostic requis.

constinit ne peut pas être utilisé conjointement avec constexpr . Lorsque la variable déclarée est une référence, constinit est équivalent à constexpr . Lorsque la variable déclarée est un objet, constexpr impose que l'objet doit avoir une initialisation statique et une destruction constante et rend l'objet qualifié const, cependant, constinit n'impose pas la destruction constante ni la qualification const. Par conséquent, un objet d'un type qui possède des constructeurs constexpr mais pas de destructeur constexpr (par exemple std:: shared_ptr < T > ) peut être déclaré avec constinit mais pas avec 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); // erreur

constinit peut également être utilisé dans une déclaration non initialisante pour indiquer au compilateur qu'une variable thread_local est déjà initialisée, réduisant la surcharge qui serait autrement engendrée par une variable de garde cachée.

extern thread_local constinit int x;
int f() { return x; } // aucune vérification d'une variable de garde nécessaire

Notes

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_constinit 201907L (C++20) constinit

Mots-clés

constinit

Exemple

#include <cassert>
constexpr int square(int i)
{
    return i * i;
}
int twice(int i)
{
    return i + i;
}
constinit int sq = square(2);    // OK : l'initialisation est effectuée à la compilation
// constinit int x_x = twice(2); // Erreur : initialiseur à la compilation requis
int square_4_gen()
{
    static constinit int pow = square(4);
    // constinit int prev = pow; // Erreur : constinit ne peut être appliqué qu'à une
                                 // variable avec durée de stockage statique ou thread
    int prev = pow;
    pow = pow * pow;
    return prev;
}
int main()
{
    assert(sq == 4);
    sq = twice(1); // Contrairement à constexpr cette valeur peut être modifiée ultérieurement à l'exécution
    assert(sq == 2);
    assert(square_4_gen() == 16);
    assert(square_4_gen() == 256);
    assert(square_4_gen() == 65536);
}

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement publié Comportement correct
CWG 2543 C++20 le comportement n'était pas clair si la variable déclarée avec constinit
est initialisée dynamiquement dans le cadre de l'initialisation statique
le programme est mal-
formé dans ce cas

Voir aussi

consteval spécificateur (C++20) spécifie qu'une fonction est une fonction immédiate , c'est-à-dire que tout appel à la fonction doit être dans une évaluation constante
constexpr spécificateur (C++11) spécifie que la valeur d'une variable ou d'une fonction peut être calculée à la compilation
expression constante définit une expression qui peut être évaluée à la compilation
initialisation constante définit les valeurs initiales des variables statiques comme une constante à la compilation
initialisation à zéro définit la valeur initiale d'un objet à zéro