2015-06-08 7 views
7

Quindi sono abituato alla gestione della memoria in C, dove free(pointer) libererà tutto lo spazio indicato da pointer. Ora mi sto confondendo quando cerco di fare qualcosa di semplice in C++.Eliminazione di un array 2D assegnato dinamicamente

Se ho un array 2D dei doppi assegnati in modo simile a questo

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

quale sarebbe il metodo corretto di liberare la memoria sul mucchio allocata da new?

I miei pensieri erano in origine questo (perché il mio cervello pensava in C):

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

Ma avevo dimenticato l'esistenza dell'operatore delete[] quindi credo che il metodo corretto è il seguente:

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

È importante comprendere la differenza tra gli operatori delete e delete[]? O posso solo supporre che ogni volta che alloco un array con ptr = new x[] devo anche deallocarlo con delete[] ptr?

+0

La versione con 'delete []' è valido. Se chiamate 'delete []' per un oggetto non array, è un ub. Puoi vedere in altre domande su SO: http://stackoverflow.com/questions/4255598/delete-vs-delete – gomons

+0

Grazie, ho avuto problemi a trovare messaggi del genere per qualche motivo ... ma questo praticamente lo risolve. Ho contrassegnato questo come duplicato di quella domanda – Alex

risposta

8

In realtà, una matrice di puntatori a cui punta un puntatore è ancora un array di tipi di dati o numeri interi per contenere gli indirizzi di memoria. Dovresti usare delete[] per entrambi.

Inoltre, sì, uno new[] implica uno delete[].

Quando si crea un array di array, il gioco è in realtà la creazione di un array di numeri che accadono per contenere l'indirizzo di memoria per un altro serie di numeri. Indipendentemente da ciò, sono entrambi array di numeri, quindi elimina entrambi con 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

Per essere chiari, il tipo di puntatore non è necessariamente un 'int' o un' long long' o un altro tipo. Lo standard definisce i tipi specifici su cui è possibile eseguire il cast che sono tipi aritmetici: 'std :: intptr_t' e' std :: uintptr_t'. A causa delle differenze di dimensioni (e probabilmente di alcune cose davvero strane, se puoi immaginare un'architettura bizzarra in cui i puntatori sono 'double'),' int' e 'std :: intptr_t' potrebbero essere di dimensioni diverse (ad esempio,' int '32-bit e valori 'std :: uintptr_t' a 64 bit). – VermillionAzure