Ich habe versucht, ::delete
eine Klasse in der davon zu fordern operator delete
. Aber der Destruktor wird nicht aufgerufen.
Ich habe eine Klasse definiert, MyClass
deren operator delete
überladen wurde. Das Globale operator delete
ist ebenfalls überlastet. Die Überladung operator delete
von MyClass
ruft 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 delete
von MyClass
.
Erwartet:
Es gibt zwei Aufrufe an den Destruktor. Eine vor dem Aufruf der überladenen operator delete
von MyClass
. Ein anderer vor dem Aufruf der globalen operator delete
.
::delete p;
verursacht undefiniertes Verhalten, da der Typ von *p
nicht 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)size
Bytes zuweisen . Es sollte nicht versucht werden, eine Instanz von vollständig zu erstellenMyClass
. Der Konstruktor vonMyClass
wird nach ausgeführtMyClass::operator new()
. Dann ruft derdelete
Ausdruck inmain()
den Destruktor auf und gibt den Speicher frei (ohne den Destruktor erneut aufzurufen). Der::delete p
Ausdruck hat keine Informationen über die Art derp
Objektpunkte an, dap
eine istvoid *
, kann so nicht den Destruktor aufrufen.