2010-12-03 4 views
3

Ich habe gerade angefangen meine Container-Klasse und schon bin ich mit Fragen:Fehler in Klassendestruktor

class Container 
{ 
    private: 

    string* BasePointer; // The starting pointer. 
    unsigned int Capacity; // The number of values the container can hold. 

    public: 

    Container() // Default constructor. 
    { 
     Capacity = 1; 
     BasePointer = new string[Capacity]; 
    } 

    ~Container() // Destructor. 
    { 
     delete BasePointer; // Delete the container to prevent memory leaking. 
    } 
}; 

Ich erhalte den Fehler Container Classes(26467) malloc: *** error for object 0x100100088: pointer being freed was not allocated. Was mache ich falsch?

+1

Es heißt * Destruktor *, wie in der Zerstörung. Nicht Dekonstruktor. :) – jalf

+0

@jalf Richtig, sorry. – Maxpm

Antwort

7

Die XXX ptr = new XXX[size] sollte mit Array-Version delete [] ptr, nicht nur regulär delete übereinstimmen.

Lesen Sie über free store management in C++, und wie James erinnert uns - folgen Sie den rule of three in Fällen wie diesem.

+0

genau was ich dachte –

+0

Danke. Gibt es einen syntaktischen Grund für das '[]'? Kann es ein optionales Argument oder etwas enthalten? – Maxpm

+1

Nein, Sie dürfen kein Argument angeben. Und der Grund ist - na ja, was es tut ist anders als was löscht, also braucht es einen anderen Namen;) – etarion

4

müssen Sie löschen, verwenden Sie []

delete[] BasePointer; 
1

Hallo, wenn Sie Array erstellen Sie [] BasePointer verwenden müssen, löschen;

0

Um expliziter als die anderen zu sein - wenn Sie einen Array-Typ new -ed, müssen Sie den Zeiger mit delete[] löschen.

Dies nicht nur passieren, wenn Sie new T[size] verwenden, sollten Sie das folgende Beispiel:

typedef int T[42]; 
int* x = new T; 
delete[] x; // needs delete[] though you used new without [] 

Auf einem allgemeinen Hinweis, wenn Ihr Objekt Objekt eines „besitzt“ es über einen Zeiger hält, sollten Sie prüfen, mit ein intelligenter Zeiger (wie boost :: scoped_array) dafür. Auf diese Weise brauchen Sie sich keine Gedanken über Dekonstruktion Sorge, was passiert, wenn eine Ausnahme ausgelöst wird, die Zuweisung op Implementierung und Konstruktor kopieren ...

2

andere schon erwähnt haben, dass Sie nicht übereinstimmen new[] mit delete haben und Sie müssen delete ändern delete[], um es zu beheben. Dies ist jedoch nur der erste Ihrer Probleme.

Sie müssen auch den Kopierkonstruktor und den Kopierzuweisungsoperator implementieren (oder zumindest als privat deklarieren). Andernfalls darüber nachdenken, was passiert, wenn Sie dies tun:

{ 
    Container c1; 
    Container c2(c1); 
} // c2.~Container(); // frees the memory pointed to by 'BasePointer' 
    // c1.~Container(); // also frees the memory pointed to by 'BasePointer'. 

Seit dem BasePointer Mitglied beiden c1 und c2 Punkte auf das gleiche Array, es zweimal freigegeben wird.

Es gibt einige einfacher zu bedienende Alternativen:

  • Betrachten wir ein std::vector überall verwenden Sie sonst eine dynamisch zugewiesene Array verwenden können. Da Ihre Klasse Container heißt, nehme ich an, dass Sie versuchen, einen Ressourcenbesitz Container zu implementieren, also vielleicht möchten Sie dies nicht verwenden.

  • Verwenden Sie eine boost::scoped_ptr oder std::unique_ptr (wenn Ihr Compiler dies unterstützt), um den Besitz des Zeigers zu verwalten. Beides unterdrückt die Generierung des implizit deklarierten Kopierkonstruktors und zwingt Sie, Ihre eigenen zu implementieren, wenn Sie tatsächlich versuchen, sie zu verwenden.

Auch wenn Sie eine Container implementieren, sollten Sie dennoch die Vorteile von primitiveren Container nehmen für Sie die schwere Arbeit zu tun (oder zumindest die primitive Behälter reimplementieren, so dass die schwere Arbeit in einem kleinen konsolidiert Reihe von Dienstprogrammen).

Schließlich, als stilistischer Punkt, müssen Sie nicht malloc für einen Container verwenden. Die Standardbibliothek stellt std::allocator zur Verfügung, die verwendet werden kann, um Platz für Objekte zuzuweisen und sie zu konstruieren.