De la difficulté de la suppression de vecteur de pointeurs
J'ai un gestionnaire de classe de la tenue d'un vecteur de pointeurs vers une classe de base virtuelle pour permettre une variété de classes enfant pour y être stockées. Dans le destructeur de ce gestionnaire de classe, je le veux pour faire défiler tous les pointeurs qu'il détient et de les supprimer. Cependant, j'ai essayé un certain nombre de méthodes que j'ai rencontré et le programme plante lors de l'exécution.
L'actuel code que j'ai est indiqué ci-dessous:-
for (std::vector<GameState*>::iterator it = gamestates_.begin(); it != gamestates_.end(); ++it){
delete *it;
it = gamestates_.erase(it);
}
Une chose que je n'ai pas encore essayé est à l'aide de unique_ptr, mais je suis sûr que ce doit être capable de les gérer sans les utiliser. S'il vous plaît corrigez-moi si je me trompe.
Edit: je suis conscient que je devrais effacer le vecteur après la boucle, mais c'est ce que j'ai après avoir essayé chaque méthode normale de supprimer les pointeurs. Il ne semble pas aimer la commande supprimer.
OriginalL'auteur James Richmond | 2013-09-02
Vous devez vous connecter pour publier un commentaire.
L'effacement d'un élément à partir du vecteur d'invalider l'itérateur, de sorte que vous ne pouvez pas continuer à l'itération par la suite. Dans ce cas, je ne serais pas effacer les éléments à l'intérieur de la boucle; j'avais clairement le vecteur par la suite:
Bien que, si c'est dans le destructeur et le vecteur est sur le point d'être détruit, il n'y a pas de point de compensation.
Si vous avez besoin d'effacer à l'intérieur d'une boucle (peut-être parce que vous voulez effacer certains éléments), alors vous avez besoin d'un peu plus de soin de conserver l'itérateur valide:
Si vous ne souhaitez gérer la dynamique des objets par la vapeur d'eau par cela, alors assurez-vous de suivre les La règle de Trois: vous aurez besoin de mettre en œuvre (ou supprimer) le constructeur de copie et de copie opérateur d'affectation pour éviter les "superficielle" de la copie, vous laissant avec deux vecteurs qui essayez de supprimer les mêmes objets. Vous aurez également besoin de prendre soin de supprimer les objets en tout autre lieu qui supprime ou remplace. Stocker des pointeurs intelligents (ou les objets eux-mêmes, si vous n'avez pas besoin de pointeurs pour polymorphisme) va prendre soin de toutes ces choses pour vous, alors je vous recommandons de toujours.
La cause la plus probable est que vous n'êtes pas en suivant la Règle de Trois, et sont accidentellement en essayant de supprimer les objets mêmes deux fois après la copie du vecteur. Il est également possible que
GameState
est une classe de base et vous avez oublié de lui donner un destructeur virtuel, ou que les pointeurs ont été corrompu par un autre code.Qu'est-ce exactement "ne fonctionne pas"?
Le
delete
commande est fine, si c'est un pointeur valide. Êtes-vous accidentellement la copie du vecteur et de supprimer les objets deux fois? EstGameState
une classe de base, avec différents types pour les objets réels? Si oui, assurez-vous qu'il a un destructeur virtuel. Si non, pourquoi êtes-vous stocker des pointeurs en premier lieu?Gamestate détient les appels virtuels pour l'initialisation, le rendu, la mise à jour et de près, mais à chaque enfant de il serait également tenir un certain nombre de leurs propres fonctions et de variables. Depuis je veux seulement un exécutant à la fois le gestionnaire d'appels init lorsque l'état est active et attentive lors de son fait. Le destructeur est essentiellement vide, et il ya une ligne de près l'état actif directement au-dessus de la ligne que j'ai cités. J'espère que ces classes pour être assez grande, donc j'essayais d'économiser de l'espace en les stockant sur le tas. seraient-ils encore besoin d'un destructeur virtuel de la classe de base si elles seraient essentiellement vide.
Oui, vous avez toujours besoin d'un destructeur virtuel pour supprimer via une base de pointeur de classe. Assurez-vous que
GameState
en a un, et aussi assurez-vous que le gestionnaire de classe n'est pas de copier accidentellement le vecteur.OriginalL'auteur Mike Seymour
Votre itérateur est mis à jour deux fois à chaque tour de boucle:
et
Vous avez besoin seulement le premier - il déjà des points lors de la prochaine "objet" dans le conteneur.
OriginalL'auteur Mats Petersson
L'effacement d'un élément de vecteur invalide les itérateurs. Supprimer les objets pointeur par les éléments et puis
clear()
le contenu du vecteur.OriginalL'auteur Marius Bancila
se débarrasser de la
++it
dans votrefor
de la boucle d'en-tête.erase
déjà avancées pour vous.Sinon, itérer, supprimer, puis après itération
.clear()
.OriginalL'auteur Yakk - Adam Nevraumont
Préfèrent utiliser
unique_ptr
. Vous dites que vous devrait être en mesure de gérer sans l'aide de leur comme si l'obtention d'un pointeur intelligent pour faire le travail pour vous, c'est une sorte de terrible imposition.Ils sont là pour rendre votre vie plus facile, vous n'avez pas à se sentir coupable de ne pas faire le dur travail à la main.
Et avec votre code existant, il suffit de ne pas appeler
erase
. Le vecteur va être détruit de toute façon, non? Il va prendre soin de tout ce que lui-même.Question dit que c'est dans le gestionnaire de la classe de destructeur, et je suis en supposant que le vecteur est un membre de la sous-objet.
OriginalL'auteur Useless
Le problème, c'est que vous êtes incrémentation
it
deux fois. Tout d'abord, lorsque vous appelezit = .erase(it)
qui retourne l'élément suivant, et puis dans la boucle++i
. Vous pouvez inadvertely sauter sur la fin et les choses peuvent aller mal, pour ne pas mentionner que vous ne supprimer que chaque deuxième élément du vecteur.Une solution simple est de tout simplement ne pas changer
it
dans la boucle (pas de++it
).Une meilleure façon serait de fait de supprimer le tableau à partir de la fin du vecteur, comme l'effacement des éléments de l'intérieur du vecteur introduit cher la migration de l'ensemble de ses éléments. Votre algorithme travail dans
N^2
temps.Essayez quelque chose comme ceci:
Vous pouvez aussi parcourir tous les éléments du vecteur et de l'effacer par la suite:
Noter également, que le
clear()
fonctionnement du vecteur se fait aussi dans son destructeur. Si la procédure de suppression est le cadre de certains processus de destruction oùgamestates_
est ulimately détruits - vous n'avez pas à appelerclear()
à tous.OriginalL'auteur CygnusX1