16

クラスのイニシャライザ リスト構文を使用できるかどうかは、クラス フィールドにデフォルト値があるかどうかに依存することがわかりました。なんで?

正確には、次のコードを検討してください。

class S
{
    public:
        int a;
};
...
int a;
S s{ a };

問題なくコンパイルされます。しかし、クラス フィールドにデフォルト値を追加すると、ビルドが停止します。

class S
{
    public:
        int a = 0;
};
...
int a;
S s{ a };

エラー 1 エラー C2440: 'initializing': 'initializer-list' から 'S' に変換できません

なんで?そのようなコンストラクターの生成に他に何が影響しますか?

4

3 に答える 3

19

C++14では、コードは有効であり、C++14 互換コンパイラでコンパイルする必要があります。


ただし、 C++11では:

のデフォルト値がない場合a、タイプは集約であるため、集約の初期化を実行できます。

集計は、次のいずれかのタイプです。

  • 配列型

  • を持つクラス型 (通常は構造体または共用体)

    • プライベートまたは保護された非静的データ メンバーなし
    • パブリックベースから継承されたものを含め、ユーザー提供のコンストラクターはありません (C++17以上) (明示的にデフォルト設定または削除されたコンストラクターが許可されます) (C++11以上)
    • virtual、private、または protected (C++17以上) 基本クラスはありません
    • 仮想メンバ関数なし
    • デフォルトのメンバー初期化子なし ( C++11 以降、C++14 まで)

attribute のデフォルト値を追加するとすぐにa、タイプが集約でなくなるため、集約の初期化を実行できなくなります。

于 2016-06-29T12:28:50.403 に答える
4

表示されているコードは、gcc 6.1.1 で問題なくコンパイルされます。C++14 を完全にはサポートしていない古いコンパイラを使用している可能性があります。

$ cat t.C
class S
{
public:
  int a = 0;
};


void foo()
{
    int a=4;

    S s{a};
}
$ g++ -std=c++1z -g -c -o t.o t.C
$ g++ --version
g++ (GCC) 6.1.1 20160510 (Red Hat 6.1.1-2)
Copyright (C) 2016 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
于 2016-06-29T12:28:18.163 に答える
2

どちらの場合も、 の既定のコンストラクターはS引数を取りません。クラスの形式は、既定のコンストラクターの生成には影響しません。さらに、 を受け取る暗黙的に生成されたコンストラクターはありませんint

Saggregateの場合、使用法はのコンストラクタS s = { arguments_opt };を呼び出しません。代わりに、集計の初期化Sと呼ばれるものを呼び出します。集合体は、そのクラスのオブジェクトをコンストラクター呼び出しなしで作成できる唯一のクラスです。

が集約でないS場合にのみ、引数リストを のコンストラクタのパラメータと一致させようとします。S s = { arguments_opt };S

(他の人が説明したように、C++ 11では、非静的データメンバーにブレースまたはイコールイニシャライザーを提供すると、クラスが集約されなくなります)。

于 2016-06-30T09:25:07.030 に答える