2015-06-08 5 views
7

Итак, я привык к управлению памятью на C, где free(pointer) освободит все пространство, на которое указывает pointer. Теперь я запутываю себя, когда пытаюсь сделать что-то простое в C++.Удаление динамически выделенного 2D-массива

Если у меня есть 2D массив удваивается, выделенных таким образом, подобное этому

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

, что было бы правильным методом освобождения памяти в куче, выделенной нового?

Мои мысли были изначально это (потому что мой мозг думал в C):

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

Но я уже забыл о существовании оператора delete[], поэтому я считаю, что правильный метод заключается в следующем:

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

Важно ли понимать разницу между операторами delete и delete[]? Или я могу просто предположить, что всякий раз, когда я выделяю массив с ptr = new x[], я должен также освободить его с помощью delete[] ptr?

+0

версия с 'удалить []' является действительным. Если вы вызываете 'delete []' для объекта без массива, это ub. Вы можете видеть в других вопросах: http://stackoverflow.com/questions/4255598/delete-vs-delete – gomons

+0

Спасибо, у меня возникли проблемы с поиском сообщений по этому поводу по какой-то причине ... но это в значительной степени очистило его. Я отметил это как дубликат этого вопроса. – Alex

ответ

8

В действительности массив указателей, на которые указывает указатель, по-прежнему представляет собой массив интегральных типов данных или чисел для хранения адресов памяти. Вы должны использовать delete[] для обоих.

Кроме того, да new[] подразумевает delete[].

При создании массива массивов, вы фактически создаете массив чисел, которые происходят держать адрес памяти для другого массива чисел. Несмотря на это, они оба являются массивами чисел, поэтому удаляйте оба с 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

Чтобы быть ясным, тип указателя не обязательно является «int» или «long long» или любым другим типом. Стандарт определяет конкретные типы, которые вы можете использовать для арифметических типов: 'std :: intptr_t' и' std :: uintptr_t'. Из-за различий в размерах (и, возможно, некоторых ДЕЙСТВИТЕЛЬНО странных вещей, если вы можете представить себе странную архитектуру, где указатели «double»), 'int' и' std :: intptr_t' могут быть разных размеров (например, 32-разрядные 'int' и 64-битные значения 'std :: uintptr_t'). – VermillionAzure

Смежные вопросы