2012-07-25 22 views
5

Ho una classe basata su modelli, myFoo, che memorizza "roba" di tipo T che può essere primitiva o puntatore a tipi complessi. Quando myFoo viene cancellato, voglio rilasciare tutta la memoria associata a tutto ciò che accade per essere memorizzata. Ciò significa che ho bisogno di chiamare delete su ogni puntatore che viene memorizzato, ma potrei anche finire per chiamare delete su una primitiva. È sicuro?Posso chiamare delete su primitive?

Ho incluso uno schizzo di myFoo qui sotto per evidenziare meglio cosa sta succedendo. Non sono sicuro che il comportamento del distruttore sia ben definito.

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

Non sei specializzato per i suggerimenti? – chris

+1

Come scritto, il tuo codice non ha senso per * qualsiasi * tipo 'T', almeno semanticamente: stai mescolando le responsabilità di proprietà, e la classe sarebbe un incubo di usabilità, leggibilità e manutenibilità. In breve, non dovrebbe essere * tuo * preoccupare di cosa sia 'T', e il cliente dovrebbe fare la sua pulizia (o ovviamente usare un puntatore intelligente). –

+0

@KerrekSB: Sto scrivendo un database di sorta. Voglio inserire i dati in esso. Ha senso che il database diventi proprietario della memoria di cose che sto immagazzinando al suo interno. Altrimenti avrei bisogno di gestire tutti i dati dal database esternamente. È un po '"wtf ??" se lo faccio come suggerisci tu. – Daniel

risposta

5

L'unica cosa che si può chiamare delete su è un tipo di puntatore. È un errore chiamare delete su un int, ad esempio. Se disponi i tuoi modelli in modo che il tuo codice provi a fare qualcosa che sia un errore, il compilatore ti informerà e rifiuterà di compilare il tuo codice.

Quindi no, non devi preoccuparti di "accidentalmente" cancellare un non-puntatore.

+0

Quindi, come potrei ottenere il comportamento che descrivo? – Daniel

+0

È possibile avere modelli diversi a seconda che si desideri memorizzare i puntatori o meno. In alternativa, è possibile memorizzare istanze di una classe di puntatore intelligente e affidarsi al distruttore del puntatore intelligente per eseguire l'eliminazione. –

+0

Grazie Greg. Penso che tu (e altri) mi abbia convinto che gli indicatori intelligenti sono la strada da percorrere. – Daniel

1

Template specializzazione

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) {} 
}; 

Ripetere l'operazione per tutti i tipi primitivi. Quindi

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

Codice non selezionato.