はじめに
こちらはC++ Advent Calendar 2019の4日目になります。
参加登録がnullptrだったので遅れてではありますが投稿させていただきました。
昨日は @s51517765 さんの C++で競プロ入門、について書きます。 でした。
ありがとうございました。
明日は @Fuyutsubaki さん です。
よろしくお願いいたします。
指示付き初期化とは
C++20で集成体初期化の際にデータメンバを指定する構文が追加されました。
struct(class)
struct A
{
int x = 0;
int y = 0;
int z = 0;
};
A a{.x = 1, .y = 2, .z = 3};
// 指定がないメンバはデフォルトコンストラクタが呼ばれる
A b{.y = 2,};
// 順序が宣言順と違うとコンパイルエラー(C言語ならOK)
// A c{.y = 2, .x = 1, .z = 3};
union
共用体でも使用は可能です。
ただし、一つのみの指定です。
union B
{
int i;
float f;
};
B a{.i = 1};
// 複数指定するとコンパイルエラー
// B b{.i = 1, .f = 1.0f};
ネストされた指示付き初期化
struct A
{
int x = 0;
int y = 0;
int z = 0;
};
struct B
{
A a;
};
B a{ .a{.x=1, .y = 2, .z= 3} };
// コンパイルエラー C言語ならOK
// B b{ .a.x = 1 };
コンストラクタ定義時について
コンストラクタが定義されていた場合は指示付き初期化は使用できない。
その場合の動作についてはわからなかった。(未定義動作?)
gccだとコンパイルは通ってコンストラクタが呼ばれた。
clangだとコンパイルエラーになった。
struct A
{
int x = 0;
int y = 0;
int z = 0;
A(int,int,int):
x(3),
y(3),
z(4)
{}
};
// エラー???
// A a{.x=1, .y = 2, .z= 3};
指示付き初期化のメリット
1.メンバ変数名が指定されているので構造体の定義を見なくてもぱっと見でわかりやすい
// それぞれの値はなんだろう??
A a{1, 2, 3};
// わかりやすい
A a{.x=1, .y=2, .z=3};
2.うっかりメンバ変数の宣言順序を入れ替えてもコンパイルエラーで気づける
struct A
{
int x = 0;
- int y = 0;
int z = 0;
+ int y = 0;
};
// y=2が入っているつもりが3になってた
A a{1, 2, 3}; // OK
// 指示付き初期化なら宣言順が変わればコンパイルエラーなのでミスに気づける
A a{.x=1, .y=2, .z=3}; // Error 順序おかしい!
参考
まとめ
- C++20で指示付き初期化ができるようになった
- C言語とは違いがあるので注意