Ich habe versucht, ::deleteeine Klasse in der davon zu fordern operator delete. Aber der Destruktor wird nicht aufgerufen.
Ich habe eine Klasse definiert, MyClassderen operator deleteüberladen wurde. Das Globale operator deleteist ebenfalls überlastet. Die Überladung operator deletevon MyClassruft die überladene globale auf operator delete.
class MyClass
{
public:
MyClass() { printf("Constructing MyClass...\n"); }
virtual ~MyClass() { printf("Destroying MyClass...\n"); }
void* operator new(size_t size)
{
printf("Newing MyClass...\n");
void* p = ::new MyClass();
printf("End of newing MyClass...\n");
return p;
}
void operator delete(void* p)
{
printf("Deleting MyClass...\n");
::delete p; // Why is the destructor not called here?
printf("End of deleting MyClass...\n");
}
};
void* operator new(size_t size)
{
printf("Global newing...\n");
return malloc(size);
}
void operator delete(void* p)
{
printf("Global deleting...\n");
free(p);
}
int main(int argc, char** argv)
{
MyClass* myClass = new MyClass();
delete myClass;
return EXIT_SUCCESS;
}
Die Ausgabe ist:
Newing MyClass...
Global newing...
Constructing MyClass...
End of newing MyClass...
Constructing MyClass...
Destroying MyClass...
Deleting MyClass...
Global deleting...
End of deleting MyClass...
Tatsächlich:
Es gibt nur einen Aufruf an den destructor , bevor die überladenen Aufruf operator deletevon MyClass.
Erwartet:
Es gibt zwei Aufrufe an den Destruktor. Eine vor dem Aufruf der überladenen operator deletevon MyClass. Ein anderer vor dem Aufruf der globalen operator delete.
::delete p;verursacht undefiniertes Verhalten, da der Typ von *pnicht mit dem Typ des zu löschenden Objekts identisch ist (noch eine Basisklasse mit virtuellem Destruktor)
void*der Operand sogar explizit schlecht geformt ist. [expr.delete] / 1 : " Der Operand muss vom Zeiger auf den Objekttyp oder vom Klassentyp sein. [...] Dies impliziert, dass ein Objekt nicht mit einem Zeiger vom Typ void gelöscht werden kann, da void kein Objekttyp ist. * "@OP Ich habe meine Antwort geändert.
MyClass::operator new()sollte Rohspeicher von (mindestens)sizeBytes zuweisen . Es sollte nicht versucht werden, eine Instanz von vollständig zu erstellenMyClass. Der Konstruktor vonMyClasswird nach ausgeführtMyClass::operator new(). Dann ruft derdeleteAusdruck inmain()den Destruktor auf und gibt den Speicher frei (ohne den Destruktor erneut aufzurufen). Der::delete pAusdruck hat keine Informationen über die Art derpObjektpunkte an, dapeine istvoid *, kann so nicht den Destruktor aufrufen.