J'ai essayé d'appeler ::delete
pour une classe dans le operator delete
de celui-ci. Mais le destructeur n'est pas appelé.
J'ai défini une classe MyClass
qui operator delete
a été surchargée. Le global operator delete
est également surchargé. La surcharge operator delete
de MyClass
nommerez mondiale surchargée 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;
}
La sortie est:
Newing MyClass...
Global newing...
Constructing MyClass...
End of newing MyClass...
Constructing MyClass...
Destroying MyClass...
Deleting MyClass...
Global deleting...
End of deleting MyClass...
Réel:
Il n'y a qu'un seul appel au destructeur avant d'appeler le surchargé operator delete
de MyClass
.
Attendu:
Il y a deux appels au destructeur. Un avant d'appeler le surchargé operator delete
de MyClass
. Un autre avant d'appeler le mondial operator delete
.
::delete p;
provoque un comportement indéfini car le type de *p
n'est pas le même que le type de l'objet à supprimer (ni une classe de base avec destructeur virtuel)
void*
opérande était même explicitement mal formé. [expr.delete] / 1 : " L'opérande doit être du pointeur vers le type d'objet ou du type de classe. [...] Cela implique qu'un objet ne peut pas être supprimé à l'aide d'un pointeur de type void car void n'est pas un type d'objet. * "@OP J'ai modifié ma réponse.
MyClass::operator new()
devrait allouer de la mémoire brute, d'au moins (size
octets ) . Il ne doit pas tenter de construire complètement une instance deMyClass
. Le constructeur deMyClass
est exécuté aprèsMyClass::operator new()
. Ensuite, l'delete
expression dansmain()
appelle le destructeur et libère la mémoire (sans appeler à nouveau le destructeur). L'::delete p
expression ne contient aucune information sur le type dep
point d' objet , carp
est unvoid *
, elle ne peut donc pas appeler le destructeur.