Betrachten Sie das folgende Code-Snippet. Der Destruktor von boost :: scoped_ptr wird am Ende der Hauptfunktion aufgerufen. Der Destruktor verwendet boost :: checked_delete, um den eingekapselten Widget-Zeiger aufzuheben.
%Vor% Ich habe erwartet, dass dieser Code nicht kompiliert werden kann, da das Widget an der Stelle unvollständig ist, an der der Destruktor von scoped_ptr<Widget>
aufgerufen wird. Dies wird jedoch sauber in g ++ 4.8 und Visual Studio 2010 kompiliert. Beachten Sie die kommentierte Anweisung mit dem Ausdruck sizeof(Widget)
in der Hauptfunktion. Wenn ich es auskommentiere, wird es nicht kompilieren, was bedeutet, dass Widget
zu diesem Zeitpunkt unvollständig sein muss.
Was ist die korrekte Erklärung für dieses Verhalten?
BEARBEITEN: Einige Antworten (jetzt gelöscht) wiesen auf nicht definiertes Verhalten hin, aber ich hätte erwartet, dass die Verwendung von checked_delete in scoped_ptr
destruktor einen Kompilierungsfehler verursacht. FWIW, ich benutze Boost 1.55.
5.3.5 Löschen
[expr.delete]
5 Wenn das Objekt gelöscht unvollständigen Klassentyp an der Stelle der Deletion und die vollständige Klasse hat, einen nicht-trivialen destructor oder eine Aufhebung der Zuordnung Funktion wird das Verhalten ist nicht definiert.
Sie würden sicherlich erwarten, dass es UB ist, denn Widget::~Widget()
ist nicht-trivial, und Sie würden erwarten, dass die Sicherheit in Boost zu Fehler führt.
Nun, lasst uns höher graben:
2.2 Phasen der Übersetzung
[lex.phases]
8 Übersetzte Übersetzungseinheiten und Instanziierungseinheiten werden wie folgt kombiniert: [Anmerkung: ...] Jede übersetzte Übersetzungseinheit wird untersucht, um eine Liste der erforderlichen Instanziierungen zu erstellen. [Hinweis: Dies kann explizit angeforderte Instanzen enthalten (14.7.2). -Hinweis] Die Definitionen der erforderlichen Vorlagen sind lokalisiert. Es ist implementationsdefiniert, ob die Quelle der Übersetzungseinheiten, die diese Definitionen enthalten, verfügbar sein muss. [Hinweis: Eine Implementierung könnte ausreichende Informationen in die übersetzte Übersetzungseinheit codieren, um sicherzustellen, dass die Quelle hier nicht benötigt wird. -Ende note] Alle erforderlichen instantiations ausgeführt Instanziierung Einheiten zu produzieren [Anmerkung:. Diese sind ähnlich wie übersetzt Übersetzungseinheiten, enthalten jedoch keine Hinweise auf instanziierten Vorlagen und ohne Vorlage Definitionen. -Hinweis] Das Programm ist fehlerhaft, wenn eine Instanziierung fehlschlägt.
Sie werden gespeichert durch Phasen der Übersetzung :
Übersetze die Übersetzungseinheit, dann instanziiere Vorlagen ...
Tags und Links c++ boost incomplete-type smart-pointers scoped-ptr