2016-08-04 26 views
3

Das folgende Stück Code prints 0 compiled with vc++ und prints 1 compiled with g++ or clang++:Visual C++ Initialisierung Inkonsistenz mit gcc und Klirren

#include <iostream> 
#include <vector> 

struct S 
{ 
    S() = default; 

    std::vector<int> v{0};   
}; 

int main() 
{ 
    std::vector<S> s{{}}; 

    std::cout << s.front().v.size() << std::endl; 
} 

Ist es ein Fehler in vC++?

Wenn ein benutzerdefinierter Konstruktor bereitgestellt wird (S() {}; anstelle von S() = default;) .

+1

Sieht tatsächlich wie ein Compiler-Fehler im VC++ Compiler. –

+1

Ich erinnere mich, dass es eine bevorstehende Änderung in C++ 17 in Bezug auf einen geschweiften Klammerinitialisierer mit genau einem Element gibt. Was passiert, wenn Sie die 0 in eine 13 ändern? –

+0

@ Cheersandthth.-Alf z.B. 'std :: vector v {11,22};' erzeugt das gleiche Problem. –

Antwort

3

in der Standard-Messwert (C++ 11 n3485), 12.6.2/9 heißt:

Wenn ein gegebenes nicht-statisches Datenelement sowohl eine brace-or-equal-initializer und eine mem-initializer, die Initialisierung durch den mem-initializer angegeben wird durchgeführt, und die brace-or-equal-initializer des nicht statischen Datenelements wird ignoriert.

So wird die Frage, ob der default, das heißt, die implizit definiert Konstruktor ein mem-initializer enthält oder nicht.

Abschnitt 12.1/6 heißt es:

Der implizit definierte Default-Konstruktor führt die Reihe von Initialisierungen der Klasse, die ohne ctor-initializer (12.6.2) für diese Klasse von einem Benutzer geschriebenen Standardkonstruktors durchgeführt werden würde und eine leere compound-statement.

Dies würde bedeuten, die implizit erzeugt (default) Konstruktor keine mem-initializer s hat und in der Tat die initializer in-Klasse verwendet werden soll (die brace-or-equal-initializer in dem obigen Zitat).

MSVC ist hier falsch (keine Überraschung, wirklich).

1

Dies ist keine Antwort, sondern ein Kommentar, der Code erfordert.

Die folgende Abbildung zeigt die Compiler-Unterschiede deutlicher, denke ich:

#include <iostream> 
#include <vector> 

struct S 
{ 
    S() = default; 

    std::vector<int> v = std::vector<int>(13); 
}; 

int main() 
{ 
    std::vector<S> s{{}}; 
    std::cout << s.front().v.size() << std::endl; 
} 

Hier g ++ MinGW 5.1.0 berichtet 13 Artikel, während MSVC 2015 Update 2 Berichte 0 Produkte.

I.e. g ++ verwendet den in der Klasse angegebenen Initialisierer, während MSVC den in der Deklaration von s angegebenen verwendet. Das sieht für mich nach einem Problem mit g ++ aus. Aber ich bin mir nicht sicher: Das einzig sichere ist, dass beides nicht stimmen kann.