2011-03-26 13 views
5

¿Es esto correcto ?:delete asignada dinámicamente objeto de std :: vector

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

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

Lo de siempre: considere usar un vector de punteros compartidos, o un 'boost :: ptr_vector'. –

+1

Aquí está el enlace para aumentar los contenedores de punteros, del que Space_C0wb0y está hablando: http://www.boost.org/doc/libs/1_46_1/libs/ptr_container/doc/tutorial.html#basic-usage – yasouser

+2

You 'push_back (nuevo Enemigo) '? ¿No sabías que no es justo presionar a tu enemigo por la espalda? :-D –

Respuesta

8

Funciona, sí, pero no es un enfoque ideal.

En primer lugar, agregar 0 es solo ruido, puede eliminarlo. Pero aún mejor, solo use pop_front(). Además, no es necesario el paso intermedio, puede eliminarlo antes de eliminarlo.

Pero std::vector no es bueno como estallar desde la parte delantera, especialmente si es grande (porque los elementos restantes deben desplazarse para llenar el vacío). Si no necesita memoria contigua, use un std::deque en su lugar. O bien, si el orden no importa, se puede usar algo como esto:

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 
} 

Se intercambia el elemento frontal con el elemento de espalda, y luego lo mete fuera. Por supuesto, el orden no se conserva.

El otro problema es con su enfoque de gestión de memoria. Cada vez que tiene un código de limpieza explícito, ha hecho algo mal. Debe ser done automatically.

Utilice Boost's ptr_vector, o std::vector de smart pointers. (Nota: no use std::auto_ptr en un contenedor, está roto en este aspecto.) Para una sugerencia rápida de puntero inteligente, use std::unique_ptr (si su compilador admite C++ 0x) o std::/boost::shared_ptr.

1

Sí, está bien. Se puede simplificar un poco:

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

Para la eliminación del elemento, también se puede utilizar:

enemies.pop_back(); 

o (muy similar a la suya):

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

¿Qué llama ~ Enemy()? ¿Es el vector.erase()/vector.clear() o es el eliminar enemigos [0]? – Ryan

+1

@Ryan: 'delete' llama al destructor del objeto apuntado, luego libera la memoria. – GManNickG

2

sin duda se ve muy bien a yo. No necesita el + 0 en la línea enemies.erase, pero aparte de eso, está perfectamente bien.

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

Esto no es una excepción. Si push_back no puede asignar suficiente memoria para acomodar el nuevo puntero, se filtra el objeto Enemy.

El uso de un vector de punteros inteligentes puede resolver esto, pero en su defecto, debe reservar el espacio en el vector antes de empujar hacia atrás:

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

Ahora sabemos que push_back no puede dejar de asignar memoria, y si reserve falla, se lanza la excepción antes de crear el Enemy.

Cuestiones relacionadas