Удалить указатель на указатель (как массив массивов) - PullRequest
29 голосов
/ 16 ноября 2010

У меня есть это в моем коде:

double** desc = new double* [size_out];
for (int i = 0; i < size_out; i++)
    desc[i] = new double [size_in];

Как мне удалить это desc?

Должен ли я сделать:

delete [] desc;

или

for (int i=0; i<size_out; i++)
    delete [] desc[i];
delete [] desc;

или

for (int i=0; i<size_out; i++)
    delete [] desc[i];
delete desc;

?

Ответы [ 5 ]

21 голосов
/ 16 ноября 2010

Ваш код не должен компилироваться.Тип нового выражения массива - это указатель на тип создаваемого элемента массива (значение является указателем на первый элемент выделенного массива).

Таким образом, тип new double**[size_out] равен double ***.

Всякий раз, когда вы используете форму массива new, вы должны использовать форму массива delete, даже если вы выделяете только массив размером один.Выделены double, только указатели.

Вы действительно хотели этого вместо?

double** desc = new double*[size_out];
for (int i=0; i<size_out; i++)
    desc[i] = new double[size_in];

for (int i=0; i<size_out; i++)
    delete[] desc[i];

delete[] desc;
21 голосов
/ 16 ноября 2010

Простые правила, которым нужно следовать:

  • для каждого выделения должно быть освобождение (поэтому ex1 неверно)
  • то, что было выделено с помощью new, должно быть освобождено с помощьюdelete, использование new[] должно быть освобождено с помощью delete[], а использование malloc должно быть освобождено с использованием free (поэтому ex3 неверно)

Вывод, ex2 в порядке.

18 голосов
/ 16 ноября 2010

Ваше удаление должно отражать ваше распределение.

Поскольку вы использовали new [] для выделения внешнего массива и new [] (в цикле) для выделения внутренних массивов, сделайте то же самое для удаления. То есть: ваше второе решение правильное; delete [] внутренние массивы в цикле и, наконец, внешний массив через delete [].

Тем не менее, ( намного , намного ) лучшим решением в C ++ было бы использование вложенного std::vector:

// Declaration and initialization:
vector<vector<double> > desc(size_out, vector<double>(size_in));

// No deletion!
6 голосов
/ 16 ноября 2010

Решение 2 является правильным: каждая ячейка указывает на динамически размещенный массив, который должен быть удален с помощью delete[]. В заключение, сам массив desc должен быть удален с помощью delete[].

Бонусное решение 4 : избегайте использования массивов и переключитесь на std::vector<std::vector<double> >.

5 голосов
/ 16 ноября 2010

Я бы сделал

for (int i=0; i<size_out; i++)
    delete [] desc[i];
delete [] desc;

для каждого массива, выделенного с new [], у вас есть соответствующий delete [].

И, как говорит Рупдольф: прекратите использовать C-массивы, иначать использовать std::vector.У вас будет меньше ошибок (в сто раз меньше ошибок).

...