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
  • constinit - 変数が静的初期化(すなわち ゼロ初期化 および 定数初期化 )を持つことを表明し、そうでない場合プログラムは不適格となる。

目次

説明

constinit 指定子は、静的またはスレッド ストレージ期間 を持つ変数を宣言します。

constinit 指定子は 構造化束縛 宣言にも適用できます。この場合、 constinit は宣言によって導入される 一意に名前付けされた変数 にも適用されます。

(C++26以降)

変数が constinit で宣言された場合、その 初期化宣言 には constinit を適用しなければなりません。 constinit で宣言された変数が 動的初期化 を持つ場合(たとえ 静的初期化として実行される 場合でも)、プログラムは不適格となります。

constinit宣言が初期化宣言の時点で到達可能でない場合、プログラムは不適格となり、診断は不要である。

constinit constexpr と同時に使用できません。宣言された変数が参照の場合、 constinit constexpr と同等です。宣言された変数がオブジェクトの場合、 constexpr はオブジェクトが静的初期化と定数破棄を持つことを要求し、さらにオブジェクトをconst修飾しますが、 constinit は定数破棄とconst修飾を要求しません。その結果、constexprコンストラクタを持ちconstexprデストラクタを持たない型(例: std:: shared_ptr < T > )のオブジェクトは constinit で宣言できますが、 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); // エラー

constinit は非初期化宣言でも使用でき、 thread_local 変数が既に初期化済みであることをコンパイラに伝えるために用いられます。これにより、 隠れたガード変数によるオーバーヘッドを削減 できます。

extern thread_local constinit int x;
int f() { return x; } // ガード変数のチェックは不要

注記

機能テストマクロ 規格 機能
__cpp_constinit 201907L (C++20) constinit

キーワード

constinit

#include <cassert>
constexpr int square(int i)
{
    return i * i;
}
int twice(int i)
{
    return i + i;
}
constinit int sq = square(2);    // OK: 初期化はコンパイル時に行われる
// constinit int x_x = twice(2); // エラー: コンパイル時初期化子が必要
int square_4_gen()
{
    static constinit int pow = square(4);
    // constinit int prev = pow; // エラー: constinitは静的またはスレッド記憶域期間を持つ変数にのみ適用可能
    int prev = pow;
    pow = pow * pow;
    return prev;
}
int main()
{
    assert(sq == 4);
    sq = twice(1); // constexprとは異なり、この値は後で実行時に変更可能
    assert(sq == 2);
    assert(square_4_gen() == 16);
    assert(square_4_gen() == 256);
    assert(square_4_gen() == 65536);
}

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
CWG 2543 C++20 constinit で宣言された変数が静的初期化の一部として動的に初期化される場合の動作が不明確であった この場合、プログラムは不適格となる

関連項目

consteval 指定子 (C++20) 関数が 即時関数 であることを指定する。つまり、関数へのすべての呼び出しは定数評価で行われなければならない
constexpr 指定子 (C++11) 変数または関数の値がコンパイル時に計算可能であることを指定する
定数式 コンパイル時に評価可能な を定義する
定数初期化 静的 変数の初期値をコンパイル時定数に設定する
ゼロ初期化 オブジェクトの初期値をゼロに設定する