Le destructeur libère-t-il la mémoire affectée à l'objet auquel il appartient ou est-il simplement appelé pour effectuer un nettoyage de dernière minute avant que l'objet ne soit désalloué par le compilateur?Destructeurs en C++
Répondre
Le 'compilateur' ne supprime rien. Il crée du code qui fait les choses à l'exécution.
Lorsque vous écrivez delete somePointer;
le compilateur, en substance, écrit:
if (has_virtual_destructor(* somePointer )) {
// virtual dispatch to a compiler-generated function
dynamic_cast< true_dynamic_type * >(somePointer)->destroy_dynamic_type();
/* contents of true_dynamic_type::destroy_dynamic_type() {
this->~true_dynamic_type();
operator delete(this); // executed within class context
} */
} else {
somePointer->~ClassName();
operator delete(somePointer);
}
En d'autres termes, le destructor est appelé, puis opérateur delete est appelé à libérer le stockage.
Si le destructeur est virtuel, une répartition virtuelle est utilisée pour effectuer toute l'opération sur l'objet sous sa forme la plus dérivée. Une manière courante d'implémenter ceci est d'ajouter des arguments cachés à chaque destructeur virtuel. Notez que l'instruction de niveau supérieur if ne fait pas vraiment partie du code généré;
le compilateur prend cette décision lors de la compilation.
Cela fait beaucoup de upvotes; v) ... peut-être mentionner la distribution à la vraie dynamique tapez dans le cas d'un destructeur virtuel. (De plus, la façon dont la recherche 'delete de l'opérateur 'fonctionne,' delete' est en fait appelée depuis un destructeur virtuel "en charge", sans parler de la confusion d'une trace de profil.) – Potatoswatter
@potatoswatter: feel feee to edit . Je ne peux pas expliquer le glissement de terrain, j'ai juste tapé l'évidence. – bmargulies
Un "nitpick" mineur: if (has_virtual_destructor ... 'n'est * pas * exécuté à l'exécution, le * compiler * peut décider pour chaque type (dépendant seulement du type * static *) s'il a un destructeur virtuel ou non virtuel et d'émettre du code approprié pour les deux situations Pas sûr de ce qui se passe quand vous essayez de supprimer un void * mais je suppose que ce sera UB –
Le destructeur est appelé pour permettre à l'objet d'effectuer un nettoyage ainsi que pour détruire tout autre objet créé par l'objet lui-même.
Le système d'exploitation s'occupera de désallouer l'objet lui-même après avoir terminé le destructeur.
1) destructor ne fait pas partie de l'objet, il appartient à la classe
2) Il appelle destructor pour tous les types définis par l'utilisateur (objets de classe) dans sa catégorie.
3) Le nettoyage est une activité facultative qui se fait que si elle est vraiment nécessaire
La mémoire est désallouée juste après la sortie de la fonction destructor et avant l'exécution retourne à l'appel ou le point « supprimer » où une instance d'objet va hors champ. En théorie, il est possible de configurer un gestionnaire de mémoire différent pour gérer new et delete, mais ce serait un changement explicite du comportement par défaut.
Plus spécifiquement, personne, sauf le programmeur, ne libère de la mémoire en C++. Si l'objet est sur la pile, il réside dans l'espace mémoire du programme et prend de l'espace pendant la durée de vie du programme. S'il est sur le tas, celui qui a créé l'objet est responsable de le désallouer. C'est ce que delete
fait. Cela nous amène au destructeur - si vous créez des objets dans votre classe, le destructeur vous permet de les supprimer lorsque la classe quitte la portée. Il vous permet de "éteindre les lumières quand vous partez".
Il n'y a pas de "programmeur". Si je suis programmeur, écris une classe avec une variable membre de type std :: vector , Je n'ai pas besoin, et ne dois pas écrire co de le supprimer. Le compilateur générera automatiquement du code pour appeler le destructeur de vecteurs std :: qu'un autre programmeur a quelque part écrit à un moment donné, et mis à disposition dans le fichier d'en-tête
Il y a toujours un "programmeur" même si ce n'est pas spécifiquement vous - les ordinateurs ne tuent pas les gens, les gens tuent les gens. Ou fuir la mémoire, peu importe. Si vous créez une variable membre de std :: vector, elle se trouve sur la pile. Pas d'allocation, pas de responsabilité. Si votre std :: vector alloue la mémoire interne en tas, alors "le programmeur" est le programmeur de std :: vector, pas vous, donc vous ne devriez pas avoir à vous en soucier. – Matt
Les destructeurs appellent automatiquement les destructeurs sur les variables membres de l'objet en cours de destruction. Ces destructeurs peuvent ou non libérer de la mémoire. Cependant, un pointeur n'a pas de destructeur, ou si vous préférez, le destructeur d'un pointeur ne fait rien. Cela ne libère pas la mémoire vers laquelle il pointe. Si un objet contient un pointeur sur un objet obtenu à partir de "new" ou "malloc", il appartient au programmeur de cet objet de faire en sorte que le destructeur fasse la bonne chose. Vous devez programmer votre destructeur pour "supprimer" ou "libérer" la mémoire si elle fait partie de l'objet en cours de destruction. Par exemple, un objet "vectoriel" obtient généralement de la mémoire à partir du tas, car la quantité de mémoire requise n'est généralement pas connue au moment de la compilation. Cette mémoire fait conceptuellement partie de l'objet vectoriel, et donc le programmeur de la classe de vecteurs doit appeler "delete" dessus dans le destructeur. Les classes standard de bibliothèque de modèles comme std :: vector le font correctement.D'autre part, certains objets contiennent des références à d'autres objets. Par contre, certains objets contiennent des références à d'autres objets. Un dictionnaire ou un index contiendra des références (pointeurs) à des objets qui n'en font pas partie conceptuellement. Cette mémoire ne doit pas être libérée par le destructeur. (Si vous supprimez votre numéro de téléphone du répertoire, vous ne voulez pas que votre téléphone disparaisse automatiquement.)
Il y a des exceptions dont le débutant n'a pas besoin. L'un est lorsque l'objet et ses conteneurs sont programmés pour utiliser le comptage de références, et l'objet référencé n'est réellement libéré que lorsque le dernier objet qui s'y réfère le laisse partir. Une autre exception est dans le cas du "placement nouveau".
Un destructeur doit supprimer tous les objets alloués dynamiquement détenus par l'objet du destructeur, mais le destructeur n'est pas responsable de libérer la mémoire de son objet. –