2012-07-25 13 views
5

Tengo una clase de plantilla, myFoo, que almacena "cosas" de tipo T que pueden ser primitivas o punteros a tipos complejos. Cuando myFoo se elimina, deseo liberar toda la memoria asociada con todo lo que sucede al almacenar. Esto significa que necesito llamar a eliminar en cada puntero que se almacena, pero también podría terminar llamando a eliminar en una primitiva. ¿Esto es seguro?¿Puedo llamar eliminar en primitivas?

He incluido un boceto de myFoo a continuación para destacar mejor lo que está sucediendo. No estoy seguro si el comportamiento del destructor está bien definido.

template<class T> 
class myFoo 
{ 
    public: 
     myFoo(int size) 
     { 
      size_ = size; 
      T* foo = new T[size_]; 
     } 

     void addFoo(T tmp, int index) 
     { 
      foo[index] = tmp; 
     } 

     virtual ~myFoo() 
     { 
      for(int i=0; i < size_; i++) 
      { 
       delete foo[i]; 
      } 
      delete [] foo; 
     } 

    private: 
     int size_; 
     T* foo; 
} 
+0

¿No puedes especializarte para punteros? – chris

+1

Tal como está escrito, su código no tiene sentido para * any * tipo 'T', al menos semánticamente: está confundiendo responsabilidades de propiedad, y la clase sería una pesadilla de usabilidad, legibilidad y mantenibilidad. En resumen, no debe ser * su * preocupación lo que 'T 'es, y el cliente debe hacer su propia limpieza (o, por supuesto, utilizar un puntero inteligente). –

+0

@KerrekSB: Estoy escribiendo una base de datos de tipo. Quiero insertar datos en él. Tiene sentido que la base de datos se apropie de la memoria de las cosas que estoy almacenando dentro de ella. De lo contrario, tendría que gestionar todos los datos de la base de datos externamente. Es un poco "¿verdad?" si lo hago como sugieres. – Daniel

Respuesta

5

El único que se puede llamar en delete es un tipo de puntero. Es un error llamar al delete en un int, por ejemplo. Si organiza sus plantillas para que su código intente hacer algo que sea un error, el compilador le informará y se negará a compilar su código.

Así que no, no tiene que preocuparse por la eliminación "accidental" de un puntero.

+0

Entonces, ¿cómo podría lograr el comportamiento que describo? – Daniel

+0

Puede tener diferentes plantillas dependiendo de si desea almacenar punteros o no. O bien, puede almacenar instancias de una clase de puntero inteligente y confiar en el destructor del puntero inteligente para realizar la eliminación. –

+0

Gracias Greg. Creo que usted (y otros) me han convencido de que los indicadores inteligentes son el camino a seguir. – Daniel

1

especialización de plantilla

template <class T> struct delete_it; 

template <class T> struct delete_it<T*> 
{ 
    static void func(T* ptr) { delete ptr; } 
}; 

template <> struct delete_it<int> 
{ 
    static void func(int) {} 
}; 

template <> struct delete_it<double> 
{ 
    static void func(double) {} 
}; 

Repita para todos los tipos primitivos. Luego

virtual ~myFoo() 
    { 
     for(int i=0; i < size_; i++) 
     { 
      delete_it<T>::func(foo[i]); 
     } 
     delete [] foo; 
    } 

Código desmarcado.

Cuestiones relacionadas