In-class und brace initialization
-
Hallo,
sagt mal, warum ist dies?
struct S { bool b; int i = 1; }; int main() { S s = {}; cout << s.b << "/" << s.i << endl; // Asugabe: 204/1 }Sollte nicht alles auf Null sein?
Und wenn ich "S s = {false};" schreiben will, bekomme ich:error C2440: 'initializing' : cannot convert from 'initializer-list' to 'S'
Bitte um Erklärung.
Danke.
-
Diese Art Structs zu Initialisieren ist noch aus C-Zeiten und funktioniert daher nur für POD (Plain Old Data) Typen. POD heißt keinen Konstruktor/Destruktor/private Membervariablen/kein virtuellen Funktionen und sicher noch ein paar Sachen die mir gerade nicht einfallen. Dadurch das du i einen Standardwert von 1 zuweist kriegst du implizit einen Konstruktor und die Initialisierung funktioniert nicht mehr. Entweder du nimmst den Standardwert raus oder erstellst einen eigenen Konstruktor der dann auch alles auf 0 setzt.
-
Okay danke.
Aber ich dachte, das ist die tolle neue C++11 Syntax (diese Klammern)

-
Genau das nennt sich Uniform Initialization. Darum compiliert dein Beispiel mit S s = {} überhaupt erst weil das den implizit generierten Konstruktor ohne Parameter aufruft. Du könntest dein Struct so definieren:
struct S { bool b; int i; S(bool b = false, int i = 1) : b(b), i(i) { } };Dann funktioniert das alles:
S s0 = {}; // b = false, i = 1 S s1 = {true}; // b = true, i = 1 S s2 = {true, 0}; // b = true, i = 0
-
Edit: Nicht ganz akkurat.
-
Ich habe die Wurzel der Verwirrung gefunden. Es handelt sich hierbei um einen Standard'defekt' der tatsächlich erst mit C++14 bereinigt wurde: NSDMIs (non-static data member initializers) waren in C++11 in Aggregaten nicht erlaubt. In C++14 ist
Saber ein Aggregat, die Ausgabe ist garantiert0/1und{false}ist ein gültiger Initializer. VC++ hat diesen Teil wahrscheinlich nicht implementiert und verhält sich C++11-konform. Sorry für meine voreilige Vehemenz.sebi707 schrieb:
Diese Art Structs zu Initialisieren ist noch aus C-Zeiten und funktioniert daher nur für POD (Plain Old Data) Typen.
Nein. Aggregate. Die mit PODs im Übrigen nicht viel zu tun haben.
POD heißt keinen Konstruktor/Destruktor/private Membervariablen/kein virtuellen Funktionen und sicher noch ein paar Sachen die mir gerade nicht einfallen.
Ja, da gibt es eine lange Liste. Übrigens können POD-Klassen private Membervariablen haben. Kannst ja ein bisschen mit
std::is_podrumspielen um dich vertraut zu machen.Aggregate können außerdem auch Destruktoren haben. Und Konstruktoren können sie selbstverständlich auch haben, nur keine die user-provided sind.
-
Super, danke für die Infos.
-
Arcoth schrieb:
Nein. Aggregate. Die mit PODs im Übrigen nicht viel zu tun haben.
Naja, in C++03 war ein POD mindestens schonmal ein Aggregate. In C++11 wurde bei PODs dann viel geändert und die Unterschiede zwischen POD und Aggregate wurden größer. Immerhin hab ich mal wieder was neues gelernt.
-
Weil mir grad langweilig war, hier ein mini-Artikel:
POD-structs
Standardlayout-structs1 sind (mittlerweile) folgendermaßen beschränkt:
- Nur Standardlayout-Member oder -Basisklassen, wobei höchstens eine Basisklasse eines bestimmten Typs (letzteres eingeführt durch #1813).
- Keine virtuellen Funktionen oder virtuelle Basisklassen
- Alle Member haben dieselben access rights (i.e. alle entweder
public,privateoderprotected). - Member/Bitfields dürfen nicht verstreut werden.2
Kleines Beispiel:
struct A {private: int i;}; // SL struct B : A {}; // SL struct C : B {int j;}; // Kein SL; Verstreute Member struct D : B, A {}; // Kein SL: Zwei Basisklassen vom Typ ADemo.
POD-structs haben Standardlayout, dürfen aber zudem nur trivialle spezielle Memberfunktionen haben (was von der Anforderung triviale Klasse hervorgeht. Siehe auch #1363). Und sie müssen einen Destruktor und (mindestens) einen Default-Konstruktor haben.
struct A { A(char const*); }; // Kein POD struct B { B(char const*); B() = default; }; // POD struct C { C(char const*); C() = delete ; }; // PODAggregate
Die Anforderungen an Aggregate sind deutlich marginaler - und anders.
§8.5.1/1 schrieb:
An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no private or protected non-static data members (Clause 11), no base classes (Clause 10), and no virtual functions (10.3).
Gemeinsamkeiten
Die einzige Anforderung die beide stellen, ist, dass keine virtuellen Funktionen und keine virtuellen Basisklassen existieren dürfen.
Daher auch mein voriges Kommentar.Unterschiede
Eigenschaften die ein Aggregat, nicht aber ein POD-struct haben darf:
- Nicht-triviale spezielle Memberfunktionen, e.g. durch einen NSDMI wie im OP gezeigt
- Member die kein Standardlayout haben
Eigenschaften die ein POD-struct, nicht aber ein Aggregat vorzeigen kann:
private/protectedMember- Konstruktoren die keine Move-/Kopier- oder Default-Konstruktoren sind
- Basisklassen.
-------------------------------------------------------------------------------
1 Schließt Unions aus. Standardlayout-Unions sind Unions mit Standardlayout, und Standardlayout-Klassen sind entweder Standardlayout-Structs oder -Unions.
2 I.e. es darf nicht ein Member in einer Basisklasse vorhanden sein und ein zweiter in der Klasse selbst oder in einer anderen Basisklasse.
-
