Y a-t-il un problème lors de la suppression d'un objet comme celui-ci en C++?
MyCls* c = new MyCls();
void* p = (void*)c;
delete (MyCls*)p;
Ceci, tel qu'il est écrit, est légal.
Le casting revient à MyCls*
est critique. Sans cela, vous invoquerez un comportement indéfini - le destructeur MyCls ne sera pas appelé, et d'autres problèmes peuvent également survenir (comme un crash). Vous devez rétablir le type correct.
Notez également que cela peut être compliqué si plusieurs héritages sont impliqués et si plusieurs transtypages sont utilisés. Vos lancers doivent "correspondre" dans les deux sens.
Si votre code est structuré de manière à ne pas connaître le type au moment de la destruction, donnez à chaque objet supprimable une classe de base commune avec un destructeur virtuel. Ensuite, convertissez-le en classe de base avant d'appeler delete.
Le code est bien défini. Les deux transtypages sont des transtypages statiques, bien qu'il soit judicieux de rendre cela explicite (static_cast<void*>
, etc.) au lieu d'utiliser des transtypages de style C. La norme dit que si un pointeur vers un objet est converti en un pointeur vide et inversé par des transtypages statiques, il conservera sa valeur d'origine. Ainsi, votre expression finale delete
aura le même effet que delete c
.
Cela étant dit, l'utilisation de void*
Est souvent une odeur de code en C++.
Il est recommandé de définir les pointeurs sur nullptr
après la suppression, en particulier pour éviter la violation d'accès/segfault dans un autre gestionnaire de thread/événement.
auto c = new MyCls();
auto p = static_cast<void*>c;
delete static_cast<MyCls*>p;
p = nullptr;
c = nullptr;
Il est encore préférable d'utiliser des pointeurs intelligents et d'éviter complètement new
/delete
.
{
auto c = std::make_unique<MyCls>();
auto p = static_cast<void*>(c.get());
// no need to delete p
} // c will be released automatically during unwinding
En C++, les transtypages explicites tels que static_cast
Sont préférés.
Si ~MyCls()
n'est pas triviale, elle sera invoquée car vous transtypez p
en MyCls*
. La suppression d'un void*
N'invoquera pas le destructeur, ce qui pourrait entraîner une fuite de mémoire ou d'autres problèmes.