Help us understand the problem. What is going on with this article?

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

はじめに

こちらは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 順序おかしい!

参考

https://ja.cppreference.com/w/cpp/language/aggregate_initialization

まとめ

  • C++20で指示付き初期化ができるようになった
  • C言語とは違いがあるので注意
tyanmahou
C++メインでゲームプログラミングとかしてる
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away