2012-07-25 7 views
5

Ich habe eine Template-Klasse, myFoo, die "stuff" vom Typ T speichert, die entweder primitiv oder Zeiger auf komplexe Typen sein kann. Wenn myFoo gelöscht wird, möchte ich den gesamten Speicher freigeben, der mit allem verknüpft ist, was gerade gespeichert wird. Das bedeutet, dass ich für jeden gespeicherten Zeiger löschen muss, aber ich könnte auch löschen auf einem Primitiv aufrufen. Ist das sicher?Kann ich löschen auf Primitiven aufrufen?

Ich habe unten eine Skizze von myFoo eingefügt, um besser hervorzuheben, was vor sich geht. Ich bin mir nicht sicher, ob das Verhalten des Destruktors gut definiert ist.

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

Können Sie nicht für Zeiger spezialisieren? – chris

+1

Wie geschrieben, macht Ihr Code keinen Sinn für * any * Typ 'T', zumindest semantisch: Sie vermischen Verantwortlichkeiten des Eigentums, und die Klasse wäre ein Albtraum der Benutzerfreundlichkeit, Lesbarkeit und Wartbarkeit. Kurz gesagt, es sollte nicht Ihr Anliegen sein, was "T" ist, und die Klientin sollte ihre eigene Reinigung vornehmen (oder natürlich einen intelligenten Zeiger verwenden). –

+0

@KerrekSB: Ich schreibe eine Datenbank von Arten. Ich möchte Daten einfügen. Es macht Sinn, dass die Datenbank den Besitz von Dingen übernimmt, die ich darin aufbewahre. Ansonsten müsste ich alle Daten von der Datenbank extern verwalten. Es ist ein bisschen "wtf ??" wenn ich es so mache, wie du es vorschlägst. – Daniel

Antwort

5

Das einzige, was Sie delete auf ein Zeigertyp aufrufen können. Es ist ein Fehler, zum Beispiel delete auf einem int aufzurufen. Wenn Sie Ihre Vorlagen so anordnen, dass Ihr Code versucht, etwas zu tun, das ein Fehler ist, wird der Compiler Sie wissen lassen und die Kompilierung Ihres Codes ablehnen.

Also nein, Sie müssen sich keine Sorgen machen, dass Sie versehentlich einen Nicht-Zeiger löschen.

+0

Wie könnte ich das beschriebene Verhalten erreichen? – Daniel

+0

Sie könnten unterschiedliche Vorlagen haben, abhängig davon, ob Sie Zeiger speichern möchten oder nicht. Oder Sie können Instanzen einer Smart Pointer-Klasse speichern und sich auf den Destruktor des Smartpointers verlassen, um das Löschen durchzuführen. –

+0

Danke Greg. Ich denke, Sie (und andere) haben mich davon überzeugt, dass intelligente Zeiger der richtige Weg sind. – Daniel

1

Template Spezialisierung

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

Wiederholen Sie für alle primitiven Typen. Dann

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

Ungeprüfter Code.