LoginSignup
22
7

More than 3 years have passed since last update.

C++20 指示付き初期化子

Last updated at Posted at 2019-12-04

はじめに

こちらは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言語とは違いがあるので注意
22
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
7