constinit 指定子 (C++20 以降)
目次 |
[編集] 説明
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); // error
constinit は、非初期化宣言でも使用でき、thread_local 変数がすでに初期化されていることをコンパイラに伝え、そうでなければ隠れたガード変数によって発生する オーバーヘッドを削減する ことができる。
extern thread_local constinit int x; int f() { return x; } // no check of a guard variable needed
[編集] 注記
| 機能テストマクロ | 値 | 規格 | 機能 |
|---|---|---|---|
__cpp_constinit |
201907L |
(C++20) | constinit
|
[編集] キーワード
[編集] 例
#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); }
[編集] 欠陥報告
以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。
| DR | 適用対象 | 公開された動作 | 正しい動作 |
|---|---|---|---|
| CWG 2543 | C++20 | constinit で宣言された変数の動作が不明確であった場合 静的初期化の一部として動的に初期化される |
この場合、プログラムは 不正となる |
[編集] 関連項目
consteval 指定子(C++20) |
関数が即時関数であることを指定する。つまり、関数へのすべての呼び出しは定数評価内で行われなければならない。 |
constexpr 指定子(C++11) |
変数または関数の値をコンパイル時に計算できることを指定する |
| ない | コンパイル時に評価可能な式を定義する |
| 定数初期化 | 静的 変数の初期値をコンパイル時定数に設定する |
| ゼロ初期化 | オブジェクトの初期値をゼロに設定する |