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 %code% aufgerufen wird. Dies wird jedoch sauber in g ++ 4.8 und Visual Studio 2010 kompiliert. Beachten Sie die kommentierte Anweisung mit dem Ausdruck %code% in der Hauptfunktion. Wenn ich es auskommentiere, wird es nicht kompilieren, was bedeutet, dass %code% 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 %code% destruktor einen Kompilierungsfehler verursacht. FWIW, ich benutze Boost 1.55.
5.3.5 Löschen %code%
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 %code% 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 %code%
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 ...