2012-03-27 14 views
5

Quiero almacenar el objeto 10 Obj en objList, pero no sé cuándo es el uso apropiado delete en este caso. Si utilizo delete Obj; en la línea donde lo anoto en el código a continuación, ¿se almacenará el Obj en objList?Cuándo usar "eliminar"?

struct Obj { 
    int u; 
    int v; 
}; 

vector<Obj> objList; 

int main() { 
    for(int i = 0; i < 10; i++) { 
     Obj *obj = new Obj(); 
     obj->u = i; 
     obj->v = i + 1; 
     objList.push_back(*obj); 
     // Should i use "delete Obj;" here? 
    } 
} 
+5

'new' no se requiere en absoluto aquí ... crea el objeto en la pila usando' Obj obj; '. – Naveen

+1

E incluso si necesita 'new', entonces un simple 'delete' no sería suficiente - si' push_back' lanza, entonces tiene una fuga. Siempre debe usar los objetos [smart pointers] (http://stackoverflow.com/questions/106508) u otros [RAII] (http://stackoverflow.com/questions/76796) para administrar recursos dinámicos. –

Respuesta

8

Cualquier objeto creado en el montón con new necesidades que se solucionan con delete. En su código, en realidad está almacenando una copia en su colección.

objList.push_back(*Obj); 

Lo que esta línea está haciendo paso a paso es:

  1. Indirecting un puntero a la memoria de almacenamiento dinámico subyacente Obj ocupa (volviendo al objeto Obj)
  2. llamando al constructor de copia para crear un temporal copiar
  3. el almacenamiento de la copia temporal de la colección

Yo No es necesario que cree este Obj inicial en el montón, una pila asignada local será suficiente como ha señalado @Luchian Grigore.

Obj obj; 
objList.push_back(obj); 

No es necesario llamar a borrar en la copia de la colección, la colección STL se encargará de esta memoria misma cuando se quita el elemento, pero todavía tendrá que eliminar el montón objeto original asignado.

Sería mejor si almacenó sus objetos por std::shared_ptr. De esa forma se llamaría a delete cuando se eliminaran todas las referencias al Obj.

std::vector< std::shared_ptr<Obj> > vec; 
vec.push_back(std::make_shared(new Obj())); 
+0

Tenga en cuenta que esto no es una matriz de punteros, sino de objetos. –

+0

Estaba tratando de señalar que la vida útil del objeto en el espacio de almacenamiento asignado por la colección no tiene que ser administrado por el OP. :-) – Konrad

+0

Además, no es stack and heap, sino almacenamiento automático y dinámico. –

9

Sí, debería.

Debe haber un delete correspondiente para cada new en su programa.

Pero su programa no necesita la asignación dinámica:

Obj obj; 
obj.u = i; 
obj.v = i + 1; 
objList.push_back(obj); 

Además, su sintaxis estaba mal - objList.push_back(*Obj); // should be *obj, not *Obj

3

Piense en lo que sucede:

En su bucle se crea una nueva instancia de Obj y asignar algunos valores a la misma. Esta instancia se crea en tu pila, por lo que debes liberarla después. Cuando agrega la instancia al vector, crea implícitamente una copia, porque tiene un vector de objetos, no de punteros. Por lo tanto, el vector guarda su propia copia de Obj. Puede borrar su instancia de Obj.

Por cierto:

  • incluso se podría reutilizar la instancia del objeto y crear y libre fuera de su bucle
  • que no es necesario asignar la instancia Obj en el montón

Obj x ; x.u = i; x.v = i + 1; objList.push_back (x);

también haría

usted debe leer algunos artículos sobre punteros inteligentes y contenedores puntero inteligente. P.ej. boost :: scoped_ptr, boost :: shared_ptr, std :: auto_ptr. Usando estos paradigmas, generalmente no hay necesidad de llamar a eliminar por ti mismo.

2

Quiere usar el montón, por lo que le sugiero que cambie su declaración vectorial al vector de punteros, algo como esto.

vector<Obj *>objList; 

¿Por qué? Porque si es un vector de Obj, entonces las cosas que estás almacenando son en realidad copias del valor Obj de los punteros que creaste. ¡Los elementos objList y los punteros obj que creas están totalmente separados y sin relación! Así que cuando,

delete obj 

Las cosas en objList son totalmente completamente afectado en cualquier forma.
Además, vector<Obj> (sin asterisco), almacena su artículo como Obj y están en la pila , desaparecerán cuando su programa salga del alcance.

1

Bueno, la regla simple es que cada variable construida por new debe limpiarse por delete.

Sin embargo, dependiendo de su objetivo, puede que no necesite escribir el delete usted mismo.

En casa, al aprender los detalles sangrientos de la gestión de memoria, probablemente escriba tantos delete como escriba new.

Los profesionales, sin embargo, nunca usan delete en el código de aplicación (*). delete es un olor a código. Es la forma más corta de pérdidas de memoria en presencia de excepciones. Los profesionales utilizan RAII para hacer frente a las excepciones de forma segura, a saber: punteros inteligentes/contenedores inteligentes.

(*) a diferencia del código de la biblioteca, es decir, alguien escribió esa clase shared_ptr un día.

Cuestiones relacionadas