Question

Quelques heures en arrière, je tripotait un problème de fuite de mémoire et il est apparu que j'ai vraiment eu des trucs de base sur mal de Destructeurs virtuel! Permettez-moi d'expliquer ma conception de classe.

class Base
{
  virtual push_elements()
  {}
};

class Derived:public Base
{
vector<int> x;
public:
   void push_elements(){ 
      for(int i=0;i <5;i++)
         x.push_back(i); 
   }
};

void main()
{
    Base* b = new Derived();
    b->push_elements();
    delete b;
}

L'outil de vérification de limites fait état d'une fuite de mémoire dans le vecteur de classe dérivée. Et je me suis dit que le destructor n'est pas virtuel et la destructor classe dérivée est pas appelée. Et étonnamment a été réparé quand je fait le destructor virtuel. N'est pas le vecteur désallouée automatiquement, même si la destructor classe dérivée n'est pas appelé? Est-ce une bizarrerie dans l'outil BoundsChecker ou est ma compréhension erronée de destructor virtuelle?

Était-ce utile?

La solution

La suppression d'un objet de la classe dérivée par l'intermédiaire d'un pointeur de classe de base lorsque la classe de base ne comporte pas de fils de destructeur virtuel à un comportement non défini.

Qu'est-ce que vous avez observé (que la partie de la classe dérivée de l'objet n'est déséquilibré et que par conséquent ses membres ne avez jamais désalloué) est probablement le plus commun de nombreux comportements possibles, et un bon exemple des raisons pour lesquelles il est important de vous assurer vos destructeurs sont virtuelles lorsque vous utilisez cette façon polymorphisme.

Autres conseils

Si la classe de base ne dispose pas d'un destructor virtuel, le résultat de votre code est un comportement non défini, pas nécessairement le mauvais destructor appelé. Ceci est sans doute ce que BoundsChecker est diagnostiquait.

Bien que cela soit techniquement indéfini, vous avez encore besoin de connaître la méthode la plus courante de défaillance afin de la diagnostiquer. Cette méthode commune d'échec est d'appeler le mauvais destructor. Je ne connais pas d'implémentation qui échouera de toute autre manière, il est vrai que je n'utilise que deux implémentations.

La raison pour laquelle cela se produit est la même raison, la fonction « mauvais » sera appelé lorsque vous essayez de passer outre une fonction non membre virtuel et l'appeler par un pointeur de base.

Si le destructor n'est pas virtuel alors la destructor de base sera appelée. Le destructor de base nettoie l'objet de base et finitions. Il n'y a aucun moyen pour l'objet de base destructor savoir sur l'objet dérivé, il doit être appelé le destructor dérivé, et la façon de le faire, comme toute fonction, est de faire la destructor virtuelle.

Dans le C ++ FAQ Lite: "Quand devrait être mon destructor virtuel?" Lisez . (C ++ FAQ Lite est une excellente source pour toutes vos questions liées à la C ++, par la voie).

En C ++, un est un concept défini récursive destructor trivial - c'est un destructor que le compilateur écrit pour vous lorsque tous les membres de la classe (et toutes les classes de base) a un destructor trivial. (Il y a un concept similaire appelé le constructeur trivial.)

Quand un objet avec un destructor non trivial est inclus dans un objet (comme le vector dans votre exemple), le destructeur de l'objet à l'extérieur (comme votre Derived) n'est plus trivial. Même si vous ne l'avez pas écrire destructor, le compilateur C ++ écrit automatiquement un destructor qui appelle les membres de tous les destructeurs qui ont Destructeurs.

Alors, même si vous ne rien écrire, les mises en garde de l'écriture d'un destructor non virtuel s'appliquent également.

si vous venez de c #, vous aviez raison de se demander pourquoi vecteur est pas automatiquement désallouée. Mais en c ++, la gestion automatique de la mémoire est pas actif, sauf si vous utilisez Microsoft manged Extesions à C ++ (C ++ / CLI).

car il n'y a pas destructor dans la classe de base qui est virtuelle, l'objet de la classe dérivée ne sera jamais libéré et vous y par des fuites la mémoire allouée pour le membre de données vectorielles de la classe dérivée.

Destructeur est la fonction de membre de la classe dont le nom est le même nom du nom de classe et il est précédé par le signe tilde (~). Destructeur est utilisé pour détruire l'objet de la classe quand l'objet est hors de portée ou vous pouvez dire que tout le nettoyage de la destruction de la classe sont à faire dans destructor. Toute la mémoire est allouée lors de la construction de l'objet en classe obtient destructed (ou la libération de la mémoire) lorsque l'objet est hors de portée.

Trouver plus de détails sur l'exemple BoundsCheck

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top