2011-03-26 4 views
5

Est-ce exact ?:Supprimer l'objet alloué dynamiquement à partir std :: vector

std::vector<Enemy*> enemies; 
enemies.push_back(new Enemy()); 

Enemy* enemy = enemies[0]; 
enemies.erase(enemies.begin() + 0); 
delete enemy; 
+7

L'habitude: pensez à utiliser un vecteur de pointeurs partagés, ou un 'boost :: ptr_vector'. –

+1

Voici le lien pour booster les conteneurs de pointeurs, celui dont parle Space_C0wb0y: http://www.boost.org/doc/libs/1_46_1/libs/ptr_container/doc/tutorial.html#basic-usage – yasouser

+2

Vous 'push_back (nouvel Ennemi) '? Ne saviez-vous pas qu'il est injuste de pousser votre ennemi dans le dos? :-D –

Répondre

8

Cela fonctionne, oui, mais ce n'est pas une approche idéale.

Tout d'abord, ajouter 0 n'est que du bruit, vous pouvez le supprimer. Mais encore mieux, il suffit d'utiliser pop_front(). En outre, pas besoin de l'étape intermédiaire, vous pouvez supprimer avant de supprimer.

Mais std::vector n'est pas bon en raison de sa partie avant, surtout si elle est grande (car les éléments restants doivent être déplacés pour remplir le vide). Si vous n'avez pas besoin de mémoire contiguë, utilisez plutôt un std::deque. Ou, si l'ordre n'a pas d'importance, vous pouvez utiliser quelque chose comme ceci:

template <typename T, typename A> 
void unordered_pop_front(std::vector<T, A>& vec) 
{ 
    using std::swap; 
    swap(vec.front(), vec.back()); // constant time 

    vec.pop_back(); // constant time 
} 

Il permute l'élément avant avec l'élément arrière, puis pops hors tension. Bien sûr, l'ordre n'est pas conservé.

L'autre problème concerne votre approche de la gestion de la mémoire. Chaque fois que vous avez un code de nettoyage explicite, vous avez fait quelque chose de mal. Il devrait être done automatically.

Utilisez soit Boost's ptr_vector, soit un std::vector de smart pointers. (Remarque: n'utilisez pas std::auto_ptr dans un conteneur, il est cassé à cet égard.) Pour une suggestion rapide de pointeur intelligent, utilisez soit std::unique_ptr (si votre compilateur prend en charge C++ 0x), soit std::/boost::shared_ptr.

1

Oui, c'est très bien. Vous pouvez simplifier un peu:

delete enemies[0]; 
enemies.clear(); 

Pour retirer l'élément, vous pouvez également utiliser:

enemies.pop_back(); 

ou (très similaire à la vôtre):

enemies.erase(enemies.begin()); 
+0

Qu'est-ce qui appelle ~ ennemi()? Est-ce le vector.erase()/vector.clear() ou est-ce que les ennemis sont supprimés [0]? – Ryan

+1

@Ryan: 'delete' appelle le destructeur de l'objet pointé, puis libère la mémoire. – GManNickG

2

ressemble certainement bien à moi. Vous n'avez pas besoin du + 0 dans la ligne enemies.erase, mais à part ça, c'est tout à fait OK.

4
std::vector<Enemy*> enemies; 
enemies.push_back(new Enemy()); 

Ceci ne constitue pas une exception. Si push_back ne parvient pas à allouer suffisamment de mémoire pour accueillir le nouveau pointeur, alors l'objet Enemy est divulgué.

L'utilisation d'un vecteur de pointeurs intelligents peuvent résoudre ce problème, mais à défaut, vous devez réserver l'espace dans le vecteur avant de pousser en arrière:

std::vector<Enemy*> enemies; 
enemies.reserve(1); // or more generally, enemies.reserve(enemies.size()+1); 
enemies.push_back(new Enemy()); 

Maintenant, nous savons que push_back ne peut manquer d'allouer de la mémoire, et Si reserve échoue, l'exception est levée avant la création du Enemy.

Questions connexes