2012-12-16 7 views
7

Der C++ 11-Standard 8.5.4.3 sagt:Ein großer Fehler von VC++? Warum listet initializer-list nicht value-initialize eine Struktur auf?

"Wenn die Initialisierungsliste keine Elemente enthält und T ein Klassentyp mit einem Standardkonstruktor ist, wird das Objekt value-initialisiert."

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; 
} 

Ist das ein Fehler von VC++? Mein VC++ ist das neueste Nov 2012 CTP.

+0

Die Compiler-Optimierung sollte die Bereitstellung des C++ - Standards nicht beeinträchtigen. Ich denke, das hat nichts mit Optimierung zu tun. – xmllmx

+0

@KillianDS, bitte überprüfen Sie meine überarbeitete Post – xmllmx

+0

Was wird gedruckt, wenn Sie 'std :: cout << n << std :: endl;' hinzufügen? – helium

Antwort

3

Wert-Initialisierung eines nicht-aggregierten Klassentyps wird von 8.5p8 abgedeckt. In Ihrem Fall hat die (nicht gewerkschaftliche) Klasse einen implizit deklarierten Standard-No-Parameter-Konstruktor (12.1p5), der nicht gelöscht wird und trivial ist (ebenda). Somit ist die zweite Kugel von 8.5p8 gilt:

- wenn T a ist (möglicherweise cv qualifiziert) non-union Klassentyp ohne einen vom Benutzer bereitgestellte oder gelöscht Standardkonstruktors, dann wird das Objekt Null initialisiert wird und, wenn T einen nicht-trivialen Standardkonstruktor hat, default-initialisiert;

Also A sollte Null initialisiert werden, und das Programm sollte 0 drucken.

Am folgenden Programm:

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 korrekt ausgibt 0; gcc-4.6.3 gibt fälschlicherweise 42 aus; clang-3.0 wird absolut verrückt und gibt Müll aus (z.B. 574874232).

+0

Seit wann berührt die Null- oder Standardinitialisierung einer Klasse andere nicht-initialisierte Mitglieder? –

+0

@LightnessRacesinOrbit mindestens seit C++ 11 ** [dcl.init] **/5: "* [...] - wenn T ein (möglicherweise cv-qualifizierter) Nicht-Union-Klassentyp ist, jeder nicht-statisch Datenelement und jedes Basisobjekt Subobjekt ist Null-initialisiert und Padding wird auf Null Bits initialisiert; [...] * " – ecatmur