Question

Je voudrais la destructor de ma classe pour supprimer l'objet à l'exception d'un des membres, qui est supprimé ailleurs. Tout d'abord, est-ce tout à fait déraisonnable? En supposant que ce n'est pas, comment puis-je faire cela? Je pensais que créé un destructor avec un corps vide empêcherait tous les membres d'être supprimé (parce que le destructor ne rien faire), mais cela ne semble pas être le cas.

Était-ce utile?

La solution

Réponse courte :. Vous ne faites pas

Deuxième réponse :. Si le « membre » est en fait un pointeur vers une autre allocation, vous pouvez demander à ne pas supprimer l'autre allocation

Mais en général, si vous avez affecté l'autre bloc dans le constructeur, vous voulez supprimer dans le destructor. Tout le reste, il faudra une manipulation minutieuse de la « propriété » du bloc en question. Ce sera un peu comme la gestion de la mémoire dans c plaine. Possible, mais plein de dangers.

Bonne chance.

Autres conseils

Cela dépend de ce que vous entendez par « supprimé ». Si elles ne sont pas dans un pointeur intelligent, et ne sont pas explicitement supprimés, ils ne sont pas supprimés. Les membres qui ne sont qu'une partie de la classe:

class Bar {
//...
private: 
  Foo foo;
};

ne sont pas supprimés par le destructor (parce qu'ils ne sont pas alloués dynamiquement), ils sont tout simplement détruits. Ils l'intérieur de la classe « live », donc une fois qu'il est détruit, il est parti.

Si vous êtes à la recherche de la part la « propriété » entre les deux endroits, ce que vous voulez est un shared_ptr allouée dynamiquement:

#include <memory>
class Bar {
// ...
private:
  std::tr1::shared_ptr<Foo> foo;
};

Si le membre est contenu par valeur (et non par pointeur ou par référence), alors vous ne pouvez pas l'empêcher d'être supprimé et vous ne devriez pas vouloir.

Si vous voulez supprimer ailleurs au lieu, puis le rendre contenue par pointeur ou par référence.

class House
{
  Door door; //contained by value, will be destroyed when the House is
}

class House
{
  Door& door; //contained by reference, will not be destroyed when the House is
}

Le code dans le destructeur est seulement de supprimer les membres qui sont alloués dynamiquement. La destruction des membres ne sont pas en option, vous ne pouvez contrôler que la désaffectation de ce que vous explicitement à prendre avant (avec l'opérateur nouveau).

Qu'est-ce que vous voulez faire peut être obtenu en utilisant un shared_ptr, dans lequel à la fois votre classe et la part de code externe un pointeur sur le même objet externe. De cette façon, que lorsque tous les pointeurs vers cet objet hors de portée, il sera supprimé. Mais méfiez-vous de ne pas faire des références circulaires, shared_ptr n'a pas la sagesse « garbage collector ».

Bien sûr, vous pouvez utiliser un pointeur régulièrement partagé par ces endroits, mais dans la plupart des cas, une mauvaise idée, enclin à vous donner des maux de tête sur désaffectation appropriée des ressources plus tard.

Tout d'abord, si l'objet membre est contenu en valeur, il va tout simplement hors de portée lorsque l'objet conteneur est détruit, et vous ne pouvez pas l'empêcher d'être désallouée automatiquement.

Si, il est fait référence au lieu indirectement par votre objet conteneur (par exemple avec un pointeur), vous ne devez pas faire quoi que ce soit en particulier pas supprimer. Le destructor ne supprime rien à moins que vous écrivez explicitement le code pour le faire.

Quant à la question de savoir si cela est déraisonnable, je pense que ce n'est pas, en général, mais vous devez préciser (en général dans la documentation, car C ++ n'a pas prise en charge linguistique pour ce concept) ce qui est l'objet possède le membre en question.

Je pense que dans la plupart des cas, vous vous demandez des ennuis si vous ne pas détruire tout l'objet de la même action. Il semble que votre classe doit avoir une méthode de nettoyage pour ce membre, qui est appelé dans le destructor. Si, pour quelque raison que le membre doit être détruit plus tôt, la méthode peut revenir au début.

  

Tout d'abord, est-ce tout à fait   déraisonnable?

Je ne dirais pas déraisonnable, peut-être discutable.

Il est parfaitement valable pour une catégorie à posséder et devrait donc prendre soin de nettoyage, tout en ayant en même temps une référence ou un pointeur vers cet objet dans une autre classe.

Cependant, il est peut-être discutable si le second reall de classe doit avoir ce pointeur ou non, je préfère toujours utiliser une méthode get pour récupérer ce pointeur chaque fois que je besoin, par exemple en appelant une classe parent ou d'un gestionnaire de ressources.

Si vous avez dynamiquement la mémoire allouée à ce membre, il est possible une fois que vous avez partagé la référence à ce membre avant de détruire l'objet et si vous assurez le membre ne soit pas détruit dans le destructeur de l'objet. Cependant, je pense que cette pratique est pas raisonnable.

Quand vous parlez des membres de classe sont supprimés dans le destructor, vous devez faire une distinction entre les membres qui ne sont pas des pointeurs et ceux qui le sont. Disons que vous avez une classe comme ceci:


class Foo
{
public:
  Foo() {p = new int;}
 ~Foo(){}

private:
 int a;
 int *p;
};

Cette classe dispose de 2 éléments de données: un a entier et un pointeur vers un p entier. Lorsque la destructor est appelée, l'objet est détruit, ce qui signifie que les Destructeurs pour tous ses membres sont appelés. Cela se produit même si le corps du destructor est vide. Dans le cas d'un type primitif, comme un entier, appelant sa destructor signifie simplement que la mémoire qu'il occupe sera libéré. Cependant, il y a un hic quand vous détruisez un pointeur: ce qu'il pointe vers ne soit pas détruite par défaut. Pour cela, vous devez appeler explicitement delete.

Ainsi, dans notre exemple, a sera détruit lorsque le destructeur est appelé, et ainsi se p, mais pas quels que soient les points de p à. Si vous souhaitez libérer la mémoire à laquelle p points, le destructor pour Foo devrait ressembler à ceci:


~Foo() {delete p};

Alors, pour en revenir à votre question, tous les membres de votre classe qui ne sont pas des pointeurs seront détruits, peu importe quoi, quand est appelé destructor de l'objet. D'autre part, si vous avez des membres qui sont des pointeurs, quels qu'ils pointent vers ne seront pas détruits, à moins que vous appelez spécifiquement pour les supprimer dans le destructor.

Comment se fait personne n'a mentionné des pointeurs faibles et forts?
Un pointeur fort est un pointeur intelligent qui agit normalement.
Un pointeur faible est un pointeur intelligent qui ne peut se supprimer à moins que tous les pointeurs forts sont hors de portée.
pointeur fort indique la propriété, un pointeur faible indique le partage.
Regardez boost.shared_ptr et boost.weak_ptr et StrongPtr de Loki pour les implémentations.
Jetez aussi un coup d'œil à RAII . Si vous saviez RAII vous auriez su la réponse à cette question vous-même.

Il est raisonnable, mais il faut veiller à ce que le nettoyage de toutes les ressources gérées est gérée de manière implicite.

(La première ressource gérée que les gens craignent généralement de la mémoire est, mais tout ce qui peut fuir - la mémoire, les descripteurs de fichiers, les pointeurs IDispatch - doit avoir le code qui gère le nettoyage implicitement).

Pour les ressources gérées partagées par plusieurs objets (presque certainement le cas si « cet objet » est censé avoir un pointeur vers quelque chose qui est nettoyé par « cet objet »), on a besoin normalement soit un « pointeur compté de référence » pour gérer l'objet ou un « pointeur faible », en fonction de vos besoins de vie.

Pour les ressources gérées qui ne sont pas partagées (et en particulier ceux qui doivent être gérés correctement lorsque des exceptions peuvent être jetés), puis un auto_ptr ou une autre variante peut être plus approprié.

Les livres Scott Meyers efficace C ++ ont été un point de départ raisonnable pour l'apprentissage de pointeurs intelligents, mais dans la pratique, vous devriez probablement juste saisir une bibliothèque comme Info brute Boost et laisser quelqu'un d'autre vous soucier de faire les affaires de coin obscur (comme ce qui se passe si un constructeur lève une exception?) à droite.

Il est possible, mais essentiellement comme @dmckee a dit qu'il est alors question de la propriété. Si tel est le cas, vous pouvez aller pour refcounting. i.e..

class A
{

RefObj* obj;
A()
{

obj = new RefObj;

}

~A()
{
 obj->ReleaseRef();
}
}


RefObj
{

int m_iRefCounter;
RefObj()
{
m_iRefCounter = 1;
}
AddRef()
{
m_iRefCounter++;
}
ReleaseRef()
{
m_iRefCounter--
if(m_iRefCounter == 0)
{
 delete this;
}
}
}

}

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