2015-06-08 10 views
7

Also bin ich an die Speicherverwaltung in C gewöhnt, wo free(pointer) freien Speicherplatz freigibt, auf den pointer zeigt. Jetzt verwirre ich mich, wenn ich versuche, in C++ etwas Einfaches zu tun.Löschen eines dynamisch zugewiesenen 2D-Arrays

Wenn ich in einer Art und Weise ein 2D-Array von Doppel zugewiesen haben ähnlich wie diese

double** atoms = new double*[1000]; 
for(int i = 0; i < 1000; i++) 
    atoms[i] = new double[4]; 

was auf dem Heap von neuen zugewiesen die richtige Methode der Freigabe des Speichers sein würde?

Meine Gedanken waren ursprünglich das (weil mein Gehirn in C dachte):

for(int i = 0; i < 1000; i++) 
    delete atoms[i]; 
delete atoms; 

Aber ich hatte die Existenz des delete[] Betreiber vergessen, so glaube ich, die richtige Methode ist wie folgt:

for(int i = 0; i < 1000; i++) 
    delete[] atoms[i]; 
delete[] atoms; 

Ist es wichtig, den Unterschied zwischen den Operatoren delete und delete[] zu verstehen? Oder kann ich einfach davon ausgehen, dass immer, wenn ich ein Array mit ptr = new x[] zuweisen, ich es auch mit delete[] ptr freigeben muss?

+0

Die Version mit 'delete []' gültig ist. Wenn Sie 'delete []' für Nicht-Array-Objekte aufrufen, handelt es sich um ein ub. Sie können in anderen SO Fragen sehen: http://stackoverflow.com/questions/4255598/delete-vs-delete – gomons

+0

Danke, ich hatte Probleme, solche Beiträge aus irgendeinem Grund zu finden ... aber das ziemlich viel klar es. Ich markierte dies als ein Duplikat dieser Frage – Alex

Antwort

8

In Wirklichkeit ist ein Array von Zeigern, auf die ein Zeiger zeigt, immer noch ein Array von ganzzahligen Datentypen oder Zahlen, um die Speicheradressen zu halten. Sie sollten delete[] für beide verwenden.

Auch, ja, eine new[] impliziert eine delete[].

Wenn Sie ein Array von Arrays erstellen, sind Sie eigentlich ein Array von Zahlen erstellen, die die Speicheradresse für eine andere Anordnung von Zahlen halten passieren. Unabhängig davon, sie sind beide Arrays von Zahlen, so löschen Sie beide mit delete[].

http://coliru.stacked-crooked.com/a/8a625b672b66f6ce

#include <iostream> 

int main() { 

    //Hey, pointers have a finite size, no matter the indirection level! 
    std::cout << "sizeof(int*): " << sizeof(int*) << std::endl; 
    std::cout << "sizeof(int**): " << sizeof(int**) << std::endl; 
    std::cout << "sizeof(int***): " << sizeof(int***) << std::endl; 

    //Create an array of pointers that points to more arrays 
    int** matrix = new int*[5]; 
    for (int i = 0; i < 5; ++i) { 
     matrix[i] = new int[5]; 
     for (int j = 0; j < 5; ++j) { 
      matrix[i][j] = i*5 + j; 
     } 
    } 

    //Print out the matrix to verify we have created the matrix 
    for (int j = 0; j < 5; ++j) { 
     for (int i = 0; i < 5; ++i) { 
      std::cout << matrix[j][i] << std::endl; 
     } 
    } 

    //Free each sub-array 
    for(int i = 0; i < 5; ++i) { 
     delete[] matrix[i]; 
    } 
    //Free the array of pointers 
    delete[] matrix; 

    return 0; 
} 
+0

Nur um klar zu sein, ist der Typ eines Zeigers nicht unbedingt ein 'int' oder ein' long long' oder irgendein anderer Typ. Der Standard definiert bestimmte Typen, die umgewandelt werden können und die arithmetische Typen sind: 'std :: intptr_t' und' std :: uintptr_t'. Wegen der Größenunterschiede (und möglicherweise einigen wirklich seltsamen Sachen, wenn Sie sich eine seltsame Architektur vorstellen können, in der Zeiger "doppelt" sind), könnten "int" und "std :: intptr_t" möglicherweise unterschiedliche Größen haben (zB 32-Bit "int") und 64-Bit-'std :: uintptr_t'-Werte). – VermillionAzure