2017-10-30 2 views
0

Ich lese C++ 11 Norm-Entwurf (N3242 Revision) und stieß auf auf folgende Aussage:Bezug Mitglied vor der Ausführung von nicht trivial Konstruktor

(12,7 Bau und Zerstörung). Bei einem Objekt mit einem nicht-trivialen Konstruktor führt die Bezugnahme auf ein beliebiges nicht-statisches Element oder eine Basisklasse des Objekts vor Beginn der Ausführung des Konstruktors zu nicht definiertem Verhalten.

Wie ich folgende Standardkonstruktors von Foo Endnutzer besser verstehen Verhalten nicht definiert (in Stück Code i(&a.i)? Constructor von Foo nicht trivial ist (weil es benutzerdefiniert) und ich beziehe mich auf Mitglied a vor der Ausführung von Konstruktor.

struct A 
{ 
    int i; 
}; 

struct Foo 
{ 
    A a; 
    int* i; 
    Foo() : a(), i(&a.i) 
    {} 
}; 

UPD: vielleicht Nutzung Mitglied des Typs int* nicht so informativ ist (Typ int ist besser geeignet zum Beispiel)

+2

_ "Ich beziehe mich auf Mitglied a vor der Ausführung des Konstruktors." _ Nein, bist du nicht. Du hast es nur mit 'a()' konstruiert. 'a.i' ist nicht initialisiert, aber die Adresse ist OK. –

+0

Was ist mit Member 'i' vom Typ' int'? Ist es okay? Ich kann die Bedeutung einer solchen Aussage von C++ nicht verstehen 11 – LmTinyToon

+0

@underscore_d, können Sie bitte Beispiele für falsche Angaben geben? Es verwirrt mich wirklich – LmTinyToon

Antwort

2

Wie ich verstehe, hat der folgende Standardkonstruktor von Foo undefiniertes Verhalten (in Stück Code i(&a.i)?

Nein. Die von Ihnen zitierte Formulierung verwendet den Ausdruck "bevor der Konstruktor mit der Ausführung beginnt". Aber wenn wir i im mem-initializer initialisieren, wir tun, dass nacha bereits gebaut worden (seit a vor i erklärt wird), so ist dies völlig in Ordnung.

Außerdem, selbst wenn die zwei Mitglieder geschaltet wurden, wäre das Programm immer noch in Ordnung, weil A keinen nicht-trivialen Konstruktor hat.

Wenn Sie die Beispiele in diesem Abschnitt betrachten, verdeutlichen sie die Absicht des Wortlauts. Vor allem der second example:

struct W { int j; }; 
struct X : public virtual W { }; 
struct Y { 
    int* p; 
    X x; 
    Y() : p(&x.j) { // undefined, x is not yet constructed 
    } 
}; 

X hat einen nicht-trivialen Konstruktor (wegen der virtual Basis), so verweisen wir auf x, bevor es gebaut ist, aber die Initialisierung von p genau das tut. Also, UB.

+0

Wie ich verstehe, bezieht sich Standard-Anweisung auf Konstruktor des Mitglieds 'a' nicht' Foo'? – LmTinyToon

+0

@LmTinyToon Ich verstehe die Frage nicht. Die Aussage trifft hier nicht wirklich zu - sie würde gelten, wenn Sie potentiell auf ein Mitglied von 'Foo' zugreifen würden, bevor dieses' Foo'-Objekt konstruiert wurde. Innerhalb von 'Foo' haben wir keine Mitglieder mit nicht-trivialen Konstruktoren, also können wir nichts falsch machen - im Sinne dieser Klausel. – Barry

Verwandte Themen