Ich schrieb this article und bekam einige Kommentare, die mich verwirrten.Stimmt es, dass eine unique_ptr-Deklaration im Gegensatz zu einer auto_ptr-Deklaration gut definiert ist, wenn der Vorlagentyp nicht vollständig ist?
Es läuft darauf hinaus grundsätzlich bis zu meinem T2
nur als Template-Parameter verwendet, gesehen zu haben und fälschlicherweise sprang zu dem Schluss, dass ich daher die Gelegenheit, nach vorne Erklärung nehmen könnte:
struct T2;
struct T1
{
std::auto_ptr<T2> obj;
};
Das ruft UB, wenn ich don‘ t gehen auf T2
irgendwo in der gleichen TU zu definieren, weil std::auto_ptr<T2>
Anrufe delete
auf seiner internen T2*
und calling delete
on an pointer to an object of an incomplete type whose complete type has a non-trivial destructor is undefined:
[C++11: 5.3.5/5]:
Wenn Das zu löschende Objekt hat zum Löschzeitpunkt einen unvollständigen Klassentyp und die vollständige Klasse hat einen nicht-trivialen Destruktor oder eine Deallokationsfunktion, das Verhalten ist nicht definiert.
Die GCC-Toolchain Ich war zufällig — v4.3.3 (Sourcery G ++ Lite 2009q1-203) — war nett genug zu sein mit mir mit einer Notiz wissen zu lassen:
Anmerkung: weder der Destruktor noch Der klassenspezifische Operator delete wird aufgerufen, auch wenn sie deklariert werden, wenn die Klasse definiert ist.
obwohl es schwierig scheint, diese Diagnose in anderen GCC-Versionen zu erhalten.
Mein Problem war, dass es viel einfacher wäre, einen Fehler wie diese, wenn delete
ing einen Zeiger auf eine Instanz eines unvollständigen Typ schlecht gebildet wurden eher als UB zu erkennen, aber das scheint wie ein effizient lösbar Problem für eine Implementierung zu lösen, also verstehe ich, warum es UB ist.
Aber dann wurde mir gesagt, wenn ich stattdessen std::unique_ptr<T2>
verwenden würde, wäre dies sicher und konform.
n3035 sagt angeblich bei 20.9.10.2:
Der Template-Parameter
T
vonunique_ptr
kann ein unvollständiger Typ sein.
Alle finde ich in C++ 11 richtig ist:
[C++11: 20.7.1.1.1]:
/1 Die Klassenvorlage
default_delete
als die (Zerstörung Politik) Standard deleter dient der Klassenvorlageunique_ptr
./2 Der Vorlagenparameter
T
vondefault_delete
ist möglicherweise ein unvollständiger Typ.
Aber default_delete
‚s operator()
erfordert eine komplette Art:
[C++11: 20.7.1.1.2/4]:
WennT
ein unvollständiger Typ ist, wird das Programm schlecht ausgebildet.
Ich nehme meine Frage ist:
Sind die commenters auf meinem Artikel richtig zu sagen, dass eine Einheit Übersetzung nur den folgenden Code, der aus wohlgeformt ist und gut definiert? Oder sind sie falsch?
struct T2;
struct T1
{
std::unique_ptr<T2> obj;
};
Wenn sie richtig sind, wie ein Compiler dies, da zu implementieren erwartet, dass es gute Gründe dafür UB zu sein, zumindest wenn ein std::auto_ptr
verwendet wird?
Da die Formulierung "das Programm ist schlecht gebildet" (ohne explizite "und keine Diagnose erforderlich ist") und nicht z. 'Dies führt zu undefiniertem Verhalten', dies * bedeutet, dass eine Diagnose erforderlich ist (die als 'static_assert (sizeof (T)," ")' implementiert werden kann). Also ja, 'std :: unique_ptr' ist sicherer als 'std :: auto_ptr '. (Bitte beachten Sie, dass dies auf die Verwendung des Standard-Löschers "std :: default_delete " zurückzuführen ist.) –
Ich wollte klarstellen, dass "der Code wohlgeformt und wohldefiniert ist"/"es gibt UB" aren ' t die einzigen beiden möglichen Ergebnisse. (Es mag nicht das sein, was du vermitteln wolltest, aber ich möchte lieber explizit sein.) –