Je suis confus sur la façon d'utiliser les destructeurs quand j'ai un std :: vecteur de ma classe.
Donc, si je crée une classe simple comme suit: p> puis dans ma fonction principale, je fais ce qui suit: p> Je reçois un accident d'exécution dans le destructeur du test lorsque je sors de portée. Pourquoi est-ce et comment puis-je libérer sa mémoire en toute sécurité? P> P>
4 Réponses :
Le problème est que vous ne définissez pas un constructeur de copie pour Maintenant, lorsque vous repoussez votre objet dans le vecteur, il est implicitement copié avec le constructeur de copie . Ce qui entraîne deux objets pointant vers le même réseau d'INTS! Donc, à la fin, deux destructeurs tentent de supprimer le même tableau - BANG. P> Chaque fois que vous définissez une classe qui détient des membres via des pointeurs *, à part le destructeur, vous devez strong> Définir également un constructeur de copie pour cela. update2: strong> Un moyen trivial pour contourner toutes ces restrictions est de définir une matrice statique au lieu de l'alloué dynamiquement une: p> Cependant, la meilleure pratique consiste à utiliser * b> C'est-à-dire, contient des pointeurs aux membres de la sémantique de propriété (grâce à @steve Jessop pour clarification) P> P> test code>. Donc, le compilateur génère un constructeur de copie par défaut pour vous, ce qui vient de copie le contenu de l'objet - dans ce cas le pointeur INT.
std :: vecteur
Exactement. Lorsque l'objet de test est ajouté au vecteur, il est copié à l'aide du constructeur de copie. Vous devriez planter si vous essayez d'accéder également à la matrice de l'objet vectoriel.
"Chaque fois que vous définissez une classe contenant des membres du pointeur" - avec la sémantique de propriété. Un pointeur sans propriétaire La sémantique ne nécessite aucun traitement spécial de la classe, mais bien sûr, l'appelant doit s'assurer que l'on reste valide aussi longtemps que l'objet pourrait l'utiliser.
@Steve, pour moi, le confinement impliquait la propriété, mais vous avez raison, j'ai essayé de le rendre plus clair maintenant.
Votre problème est ici: Le test En outre, lorsque Vous devez définir un constructeur de copie et un opérateur d'affectation afin que lorsqu'un objet Un correctif facile est de définir votre classe comme celle-ci: P> () code> crée un objet temporaire
objet code>, qui est ensuite copié sur
TOBJ CODE>. À ce stade,
TOBJ code> et l'objet temporaire ont
gros code> défini sur le tableau. Ensuite, l'objet temporaire est détruit, qui appelle le destructeur et détruit le tableau. Alors quand
tobj code> est détruit, il essaie de détruire la matrice déjà détruite. P>
TVEC code> est détruit, il détruira ses éléments , donc le tableau déjà détruit sera encore détruit à nouveau. P>
test code> est copié, le
Big code> Array est copié, ou a une sorte de référence de référence afin qu'elle ne soit détruite tant que tous les propriétaires ne soient détruits. P>
class Test
{
private:
std::vector<int> big;
public:
Test (): big(10000) {}
};
Corriger en principe mais pas dans les détails. Test Tobj = Test () ne créera pas d'objet temporaire. Le constructeur de copie est appelé à TVEC.PUSH_BACK (TOBJ);
@shura: expression test () code> in c ++ crée un objet temporaire, par définition. Les compilateurs sont autorisés à l'optimiser, mais en général, le temporaire est créé.
@Andreyt: Je ne comprends pas votre "par définition". Vous vous dites que les compilateurs sont autorisés à l'optimiser. Et ils font. La définition se brise-t-elle à ce point? Quel compilateur utilisez-vous ce constructeur de copie d'appels pour tester o = test ()?
@shura: Tout d'abord, quand je dis "être définition", je parle spécifiquement de la subexpression Test () code>. Cette subexpression crée un objet temporaire de type
test code>, par définition donnée en 5.2.3. Deuxièmement, le tout
Test TOBJ = Test () code> en C ++ signifie littéralement "Créer un temporaire et copier-le avec Copy-Constructor". La plupart des compilateurs décideront de l'optimiser, car ils sont explicitement autorisés à, mais c'est une histoire complètement différente. De plus, Tous les compilateurs i> créeront un temporaire s'ils décident de ne pas optimiser le code (en raison des paramètres du compilateur ou du fait du contexte, etc.).
Que je connaisse un compéritier qui effectue réellement le copie n'a pas d'importance. Ce qui compte, c'est ce que dit la spécification de la langue. Enfin, Tous i> compilateurs (à moins qu'ils ne soient cassés) nécessiteront que le constructeur de copie accessible doit compiler Test TOBJ = test () code>, car conceptuellement, le code effectue Copie < / I> d'un temporaire, même si la copie réelle est optimisée. Et je ne comprends pas votre argument sur "briser la définition". Les optimisations toujours violent i> le comportement abstrait C ++, c'est pourquoi ils sont appelés optimisations. En ce sens, ils font Pause i> Divers définitions.
Sans copie-constructeur, le vecteur créera une copie plate de votre objet. Cela conduit à deux objets de type test code> référençant le même tableau
gros code>. La première instance supprime la matrice lorsqu'elle est détruite, puis la deuxième instance tente de désir d'un pointeur supprimé, ce qui est un comportement indéfini. P>
class Test { private: int big[10000]; public: };
Votre suggestion fonctionnera généralement bien, mais il existe des plates-formes où mettre un int [10000] code> sur la pile causerait des problèmes. L'attribution d'objets importants du tas est généralement plus sûr.
Il est difficile de savoir exactement quelle plate-forme l'affiche originale utilise, mais peut-être s'il savait vraiment pourquoi il doit utiliser une allocation de tas dans ce cas peut-être qu'il n'aurait peut-être pas fait ses erreurs suivantes. Eh bien, je ne sais pas, peut-être qu'il devrait simplement utiliser un std :: vecteur après tout? Et bien sûr, vous pouvez simplement créer (intelligent) des pointeurs de test pour éviter toutes ces copies inutiles
D'une manière ou d'une autre, mon DVC ++ "m'a sauvé" de ces frales. Ce code [ Ideone.com/ehzbv ] s'exécute absolument bien sur DevC ++ sous Windows. Des idées pourquoi cela pourrait se produire? Ce n'est pas bien. Je veux qu'il écrisse quand il est censé crancer!