2010-04-27 9 views
5

Me encuentro con el siguiente error.cuestión de asignación de memoria relacionada con el vector

  • Tengo una clase Foo. Las instancias de esta clase se almacenan en un estándar :: vector vec de class B.
  • en la clase Foo, estoy creando una instancia de clase A asignando memoria usando new y eliminando ese objeto en ~Foo().

el código se compila, pero me da un fallo en el tiempo de ejecución. Si desactivo delete my_a del desstructor de la clase Foo. El código funciona bien (pero habrá una fuga de memoria).

¿Podría alguien explicar por favor lo que está pasando aquí y sugerir una solución?

gracias!

class A{ 
     public: 
      A(int val); 
      ~A(){}; 
      int val_a; 

}; 

A::A(int val){ 
     val_a = val; 
     }; 

class Foo {  
     public: 
      Foo(); 
      ~Foo(); 
      void createA(); 
      A* my_a; 
}; 

Foo::Foo(){ 
    createA(); 
}; 

void Foo::createA(){ 
    my_a = new A(20); 
}; 

Foo::~Foo(){ 
    delete my_a; 

}; 



class B { 
     public: 
      vector<Foo> vec;    
      void createFoo();    
      B(){}; 
      ~B(){}; 
}; 


void B::createFoo(){ 
    vec.push_back(Foo()); 
}; 


int main(){ 
    B b; 

    int i =0; 
    for (i = 0; i < 5; i ++){ 
     std::cout<<"\n creating Foo"; 
     b.createFoo(); 
     std::cout<<"\n Foo created"; 
     } 
    std::cout<<"\nDone with Foo creation"; 

    std::cout << "\nPress RETURN to continue..."; 
    std::cin.get(); 

    return 0; 
} 

Respuesta

7

Debe implementar un constructor de copia y un operador de asignación para Foo. Cada vez que encuentres que necesitas un destructor, seguramente también necesitarás estos dos. Se usan en muchos lugares, específicamente para colocar objetos en contenedores de la Biblioteca estándar.

El constructor de copia debe tener este aspecto:

Foo :: Foo(const Foo & f) : my_a(new A(* f.my_a)) { 
} 

y el operador de asignación:

Foo & Foo :: operator=(const Foo & f) { 
    delete my_a; 
    my_a = new A(* f.my_a); 
    return * this; 
} 

O mejor aún, no cree la A instancia de la clase Foo dinámicamente:

class Foo {  
     public: 
      Foo(); 
      ~Foo(); 
      void createA(); 
      A my_a; 
}; 

Foo::Foo() : my_a(20) { 
}; 
+0

Gracias Neil. ¿Cómo debería crear una instancia de clase A entonces? Un fragmento de código sería muy apreciado. Además, cómo sería copiar el código del operador de asignación y constructur. Muchas gracias – memC

+1

Neil tienes un error tipográfico ... nuevo A (f.my_a); -> nuevo A (* f.my_a); – TimW

+0

Hola, Neil, muchas gracias por el fragmento de código. En realidad, quiero pasar el 'int val' para' my_a' mientras pongo la instancia de Foo en el vector. ¿Cómo puedo hacer eso? -> Quiero algo como esto: (por supuesto que no funciona) 'vec.push_back (Foo(): my_a (40)' – memC

2

El objeto Foo se copia y en la destrucción de cada copia, se invoca delete en el s ame el valor del puntero my_a. Implemente el operador de copia y asignación para Foo o use un puntero inteligente.

Foo(const Foo& s) : my_a(s.my_a ? new A(*s.my_a) : 0) { 
} 

Foo& operator= (const Foo& s) { 
    Foo temp(s); 
    temp.swap (*this); 
    return *this; 
} 

void swap (Foo &s) { 
    std::swap (my_a, s.my_a); 
}; 
+0

+1 para el puntero inteligente – hamishmcn

+0

gracias Tim por la respuesta. – memC

3

Si no especifica un constructor de copia, el compilador crea uno para usted. El constructor de copia generado por el compilador tiene este aspecto:

Foo::Foo(const Foo& copy) 
    : my_a(copy.my_a) 
{} 

¡Vaya! Está copiando solo el puntero pero no la memoria apuntada. Tanto su Foo() temporal en createFoo() como el copiado en el vector apuntan a la misma memoria, por lo que la memoria se elimina dos veces, lo que bloquea su programa en la segunda eliminación.

Debe crear un constructor de copia que se ve algo como esto:

Foo::Foo(const Foo& copy) 
    : my_a(new A(*copy.my_a)) 
{} 

Nota: este se bloquea si copy tiene un valor NULL my_a miembro, y también invoca al constructor de copia en A, que no se ha especificado ya sea. Entonces querrás hacer algunos cambios más. También querrá una sobrecarga operator= también.

Cuestiones relacionadas