Ho provato a convocare ::delete
una lezione in operator delete
esso. Ma il distruttore non viene chiamato.
Ho definito una classe il MyClass
cui operator delete
sovraccarico è stato. Anche il globale operator delete
è sovraccarico. Il sovraccarico operator delete
di MyClass
chiamerà il sovraccarico globale 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;
}
L'output è:
Newing MyClass...
Global newing...
Constructing MyClass...
End of newing MyClass...
Constructing MyClass...
Destroying MyClass...
Deleting MyClass...
Global deleting...
End of deleting MyClass...
Effettivo:
C'è solo una chiamata al distruttore prima di chiamare il sovraccarico operator delete
di MyClass
.
Previsto:
Ci sono due chiamate al distruttore. Uno prima di chiamare il sovraccarico operator delete
di MyClass
. Un altro prima di chiamare il globale operator delete
.
::delete p;
causa un comportamento indefinito poiché il tipo di *p
non è uguale al tipo di oggetto da eliminare (né una classe base con distruttore virtuale)
void*
l'operando è persino esplicitamente mal formato. [expr.delete] / 1 : " L'operando deve essere di puntatore al tipo di oggetto o di tipo di classe. [...] Ciò implica che un oggetto non può essere cancellato usando un puntatore di tipo void perché void non è un tipo di oggetto. * "@OP Ho modificato la mia risposta.
MyClass::operator new()
dovrebbe allocare memoria grezza, di (almeno)size
byte. Non dovrebbe tentare di costruire completamente un'istanza diMyClass
. Il costruttore diMyClass
viene eseguito dopoMyClass::operator new()
. Quindi, l'delete
espressione inmain()
chiama il distruttore e rilascia la memoria (senza chiamare nuovamente il distruttore). L'::delete p
espressione non ha informazioni sul tipo dip
punti oggetto in, poichép
è avoid *
, quindi non può invocare il distruttore.