Im folgenden Codeschnipsel d1 wird der Initialisierer d2 übergeben, der noch nicht konstruiert wurde (richtig?), also ist der d.j in D's Kopierkonstruktor ein nicht initialisierter Speicherzugriff?
%Vor%Welcher Abschnitt des C ++ Standards diskutiert die Reihenfolge der Initialisierung von Datenmembern?
Ich habe momentan kein Standardhandy, daher kann ich den Abschnitt nicht zitieren, aber die Struktur oder Klassenmitgliedsinitialisierung immer passiert in der angegebenen Reihenfolge. Die Reihenfolge, in der Mitglieder in der Konstruktorinitialisiererliste erwähnt werden, ist nicht relevant.
Gcc hat eine Warnung -Wreorder
, die warnt, wenn die Reihenfolge anders ist:
Der C ++ - Standard (ISO / IEC 14882: 2003 12.6.2 / 5, Initialisierung von Basen und Mitgliedern ) sagt:
Die Initialisierung wird in der folgenden Reihenfolge durchgeführt:
- Zunächst und nur für den Konstruktor der am weitesten abgeleiteten Klasse, wie unten beschrieben, werden virtuelle Basisklassen in der Reihenfolge initialisiert, in der sie in einer Tiefe von links nach rechts des gerichteten azyklischen Graphen von Basisklassen erscheinen , wobei "von links nach rechts" die Reihenfolge des Auftretens der Basisklassennamen im abgeleiteten ist Klassenbasis-Spezifizierer-Liste.
- Dann werden direkte Basisklassen in der Reihenfolge der Deklaration initialisiert, wie sie in der Basisspezifizierer-Liste erscheinen (unabhängig von der Reihenfolge der mem-Initialisierer).
- Nichtstatische Datenelemente werden dann in der Reihenfolge initialisiert, in der sie in der Klassendefinition deklariert wurden (wiederum unabhängig von der Reihenfolge der mem-Initialisierer).
- Schließlich wird der Rumpf des Konstruktors ausgeführt.
Der Aufzählungspunkt 3 garantiert die Reihenfolge der Initialisierung des nichtstatischen Datenelements.
In Ihrem Beispiel wird es fehlschlagen:
%Vor%Als Ergebnis wird die Initialisierungsliste d1 mit einem Verweis auf ein ungültiges Objekt (d2) erstellen.
Dies ist ein Grund, die Warnstufe für Compiler so hoch wie möglich zu setzen.
Außerdem erzwingen Sie, dass alle Warnungen als Fehler gemeldet werden.
Dieses Phänomen wird in Punkt 13 von Meyer's Effective C ++ erklärt / hervorgehoben. Es besagt, dass der Destruktor Elemente in der umgekehrten Reihenfolge seiner Konstruktoren zerstören muss, daher müssen alle Konstruktoren Elemente in der gleichen Reihenfolge initialisieren, daher initialisieren sie sie in der Reihenfolge, in der sie deklariert sind (anstelle der Reihenfolge der Initialisierungslisten) .
Ja. Ein guter Compiler sollte Sie warnen, dass A::d2
nach A::d1
initialisiert wird.
Tags und Links c++