web-dev-qa-db-ja.com

宣言時にクラスメンバーを初期化できないのはなぜですか?

宣言時にメンバーを初期化できない理由があるのではないかと思います。

class Foo
{
    int Bar = 42; // this is invalid
};

コンストラクター初期化リストを使用するのと同等。

class Foo
{
    int Bar;
public:
    Foo() : Bar(42) {}
}

私の個人的な理解では、上記の例はより表現力豊かで意図的です。さらに、これは短い構文です。そして、他の言語要素と混同する可能性はありません。

これについて公式な説明はありますか?

28
danijar

非静的メンバーの初期化は、C++ 11より前のこのようにはできませんでした。 C++ 11コンパイラーでコンパイルする場合、指定したコードを喜んで受け入れます。

そもそも許可しない理由は、データメンバー宣言が定義ではないためだと思います。導入されるオブジェクトはありません。 int x;などのデータメンバーがある場合、クラスのタイプのオブジェクトを実際に作成するまで、intオブジェクトは作成されません。したがって、このメンバーの初期化子は誤解を招く可能性があります。メンバーに値を割り当てることができるのは構築中のみです。これは、まさにメンバー初期化リストの目的です。

非静的メンバーの初期化を追加する前に、いくつかの技術的な問題を解決する必要がありました。以下の例を検討してください。

struct S {
    int i(x);
    // ...
    static int x;
};

struct T {
    int i(x);
    // ...
    typedef int x;
};

これらの構造体が解析されるとき、メンバーiの解析時に、それがデータメンバー宣言(Sのように)かメンバー関数宣言(Tのように)かがあいまいです。

追加された機能では、このparantheses構文でメンバーを初期化できないため、これは問題ではありません。次のようなbrace-or-equal-initializerを使用する必要があります。

int i = x;
int i{x};

これらはデータメンバーにしかなれないため、問題はもうありません。

非静的メンバー初期化子を提案する際に考慮しなければならなかった問題の詳細な調査については、提案 N2628 を参照してください。

24

主な理由は、初期化がオブジェクトまたはインスタンスに適用され、クラスの宣言にオブジェクトまたはインスタンスがないことです。あなたが構築を開始するまで、あなたはそれを持っていません。

この点でいくつかの進化がありました。すでに、C++ 98の標準化の最後に、委員会は、整数型の静的constメンバに対してこれを行う可能性を追加しました。これは主に、コンパイラが初期化を確認できる必要があるコンテキストで使用できるためです。 。 C++ 11では、言語が拡張されて宣言で初期化子を指定できるようになりましたが、これは単なる省略形です。実際の初期化はコンストラクターの最上部で行われます。

5
James Kanze