2012-12-16 11 views
7

C++ 11標準8.5.4.3の意味は次のとおりです。VC++の大きなバグ?なぜinitializer-listは構造体の値を初期化しないのですか?

"初期化子リストに要素がなく、Tがデフォルトコンストラクタを持つクラス型の場合、オブジェクトは値で初期化されます。"

struct A 
{ 
    int get() { return i; } 

private: 
    int i; 
}; 

int main() 
{ 
    A a = {}; 

    int n = a.get(); 
    cout << n << endl; 
    // n is a random number rather than 0 

    return 0; 
} 

これはVC++のバグですか?私のVC++は最新の11月のCTPです。

+0

コンパイラの最適化は、C++標準の規定を破るべきではありません。だから、これは最適化とは関係ないと思う。 – xmllmx

+0

@KillianDS、私の改訂された投稿を確認してください – xmllmx

+0

'std :: cout << n << std :: endl;'を追加すると何が表示されますか? – helium

答えて

3

非集約クラスタイプの値の初期化は8.5p8でカバーされています。あなたのケースでは、(非ユニオン)クラスは暗黙的に宣言されたデフォルトのデフォルトパラメータなしコンストラクタ(12.1p5)を持ちます。これは削除されず、些細です(ibid)。したがって8.5p8の第二弾が適用される:

からTがユーザ提供または削除デフォルトコンストラクタなしで(おそらくCV修飾)非組合クラス型である場合、オブジェクトはゼロで初期化されると、 Tにデフォルトではないコンストラクタがある場合は、デフォルトで初期化されます。

したがって、Aはゼロで初期化し、プログラムは0を出力する必要があります。以下のプログラムで

struct A { int get() { return i; } private: int i; }; 
#include <iostream> 
int main() { 
    char c[sizeof(A)]; 
    new (c) int{42}; 
    std::cout << (new (c) A{})->get() << '\n'; 
} 

のgcc-4.7.2が正しく0を出力します。 gcc-4.6.3は42を間違って出力します。 clang-3.0は絶対に狂ってゴミを出力します(例:574874232)。

+0

クラスは、初期化されていないクラスのメンバといつ接触するのですか? –

+0

@LightnessRacesinOrbit少なくともC++ 11以降** [dcl.init] **/5: "* [...] - Tが(おそらくcv修飾された)非共用クラス型である場合、それぞれ非静的データメンバおよび各基本クラス サブオブジェクトはゼロで初期化され、パディングは0ビットに初期化されます。[...] * " – ecatmur

関連する問題