2016-05-05 4 views
2

Ich denke, mein Destructor der Vector-Klasse sollte if Anweisung haben, um den Speicher zu löschen, den es verwendet. Wenn arr ein Element hat, wird es delete arr haben. Und wenn arr viele Mitglieder hat, muss ich delete[] arr verwenden.C++: Benötige ich eine "if" -Anweisung für Destruktor?

Können Sie mir sagen, dass das notwendig ist?

Mein Code:

class Vector { 
    double * arr; 
    short dim; 

public: 
    Vector(short d = 0): dim(d) { 
     arr = NULL; 
     if (dim < 0) { 
      dim = 0; 
     } else { 
      arr = new double[dim]; 
     } 
    } 

    ~Vector() { 
     if (arr != NULL) { 
      if (dim == 1) { 
       delete arr; 
      } else { 
       delete[] arr; 
      } 

      arr = NULL; 
      dim = 0; 
     } 
    } 
}; 
+2

"Wenn' arr' ein Mitglied hat, wird es 'delete arr' haben." Was lässt dich das denken? – juanchopanza

+0

Unzusammenhängend, ich sehe keinen Grund für das "dim" -Mitglied oder den zur Initialisierung vorgesehenen Konstruktionsparameter, signiert * zu sein. Für solche Dinge wäre 'std :: size_t' besser geeignet. – WhozCraig

+3

Das Setzen von 'arr' auf' NULL' und 'dim' auf' 0' am Ende des Destruktors ist sinnlos, da das Objekt weggeht. Niemand wird jemals diese Werte sehen. Und der Test für 'NULL' wird nicht benötigt, daher kann der Destruktor-Body viel einfacher sein:' ~ vector() {delete [] arr; } '. –

Antwort

10

Nicht nur ist es nicht notwendig, es ist einfach falsch. Alles, was mit new [] erstellt wurde, kann nur mit delete [] gelöscht werden. Andernfalls wird ein undefiniertes Verhalten erstellt.

4

Sie nie anrufen new double; überall, so dass es nicht benötigt wird. Rufen Sie immer delete [] arr; an. Überprüfen Sie für NULL wird auch nicht benötigt.

6

Nicht nur das ist nicht notwendig, aber das ist illegal, da Sie nur Speicher mit new[] reservieren. Wenn Sie new anrufen, benötigen Sie eine delete, wenn Sie new[] anrufen, benötigen Sie einen Anruf an delete[]. Sie zu mischen ist ein undefiniertes Verhalten. Ihr Vektor sollte es in etwa so aussehen:

class Vector { 
    double * arr; 
    short dim; 

public: 
    Vector(short d = 0): dim(d) { 
     if (dim > 0) 
      arr = new double[dim] 
     else 
      arr = nullptr; 
    } 

    Vector(const Vector& copy) : dim(copy.dim) { 
     if (dim > 0) { 
      arr = new double[dim] 
      // copy data here 
     } 
     else 
      arr = nullptr; 
    } 

    ~Vector() { 
     delete [] arr; 
    } 

    Vector & operator=(Vector rhs) { 
     // swap the contents of the copy. you can make a swap function to do this 
     double * temp = arr; 
     arr = rhs.arr; 
     rhs.arr = temp; 
     dim = rhs.dim; 
    } 

}; 

Jetzt sind wir richtig Kopien haben und löschen Sie wird entweder ein nicht-op auf einem nullptr oder richtig den Speicher von dem Konstruktor zugewiesen ausplanen.

+0

IMO, wenn Sie einen Kopierkonstruktor zur Verfügung gestellt haben, sollte es auch einen Kopierzuweisungsoperator geben. – HolyBlackCat

+0

@HolyBlackCat Guter Vorschlag. Ich habe es einfach weggelassen, um die Konstruktoren zu zeigen. Ich habe ein einfaches Beispiel hinzugefügt. – NathanOliver

2

Nein, das ist nicht notwendig. Stellen Sie sicher, dass beim Mischen von Speicher mit einem neuen Schlüsselwort, um den Speicher ohne eckige Klammern zu löschen, vermischen Sie sie nicht.