Почему "delete [] [] ... multiDimensionalArray;" Оператор в C ++ не существует - PullRequest
22 голосов
/ 13 октября 2008

Мне всегда было интересно, есть ли оператор для удаления многомерных массивов в стандартном языке C ++.

Если мы создали указатель на одномерный массив

int *array = new int[size];

удаление выглядит так:

delete [] array;

Отлично. Но если у нас есть двухмерный массив, мы не можем сделать

delete [][] twoDimenstionalArray;

Вместо этого мы должны зациклить и удалить элементы, как в этом примере.

Кто-нибудь может объяснить, почему?

Ответы [ 9 ]

25 голосов
/ 13 октября 2008

Технически, в C ++ нет двухмерных массивов. В качестве двумерного массива вы используете одномерный массив, каждый элемент которого является одномерным массивом. Поскольку он технически не существует, C ++ не может его удалить.

20 голосов
/ 13 октября 2008

Потому что нет возможности позвонить

int **array = new int[dim1][dim2];

Все новости / удаления должны быть сбалансированы, поэтому оператор delete [][] не имеет смысла.

new int[dim1][dim2] возвращает указатель на массив размером dim1 типа int[dim2]. Так что dim2 должно быть постоянной времени компиляции. Это похоже на распределение многомерных массивов в стеке.

7 голосов
/ 13 октября 2008

Причина, по которой удаление вызывается несколько раз в этом примере, заключается в том, что new также вызывается несколько раз. Удалить нужно вызывать для каждого нового.

Например, если я выделю 1 000 000 байтов памяти, я не смогу позже удалить записи из 200 000 - 300,00, она была выделена как один целый блок и должна быть освобождена как один целый блок.

6 голосов
/ 13 октября 2008

Причина, по которой вы должны выполнить цикл, как в приведенном вами примере, заключается в том, что количество массивов, которые необходимо удалить, неизвестно компилятору / распределителю.

Когда вы разместили свой двумерный массив, вы действительно создали N одномерных массивов. Теперь каждый из них должен быть удален, но система не знает, сколько их. Размер массива верхнего уровня, то есть массива указателей на ваши массивы второго уровня, такой же, как и любой другой массив в C: его размер не сохраняется системой.

Следовательно, нет способа реализовать delete [][], как вы описываете (без значительного изменения языка).

4 голосов
/ 13 октября 2008

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

int ** mArr = new int*[10];
for(int i=0;i<10;i++)
{
   mArr[i]=new int[10];
}

мой c ++ ржавый, я не уверен, что это синтаксически правильно, но я думаю, что это близко.

3 голосов
/ 26 апреля 2011

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

Синтаксис int array[ROWS][COLS];, разрешенный для статически выделенных массивов, является просто абстракцией для программистов, которые в действительности создают одномерный массив int array[ROWS*COLS];. Но в процессе компиляции (когда размеры размерности COLS и ROWS должны быть постоянными по стандарту), компилятор также запоминает размер этих измерений, которые необходимы для последующего обращения к элементам с использованием синтаксиса, например, array[x][y] = 45. Компилятор, известный как этот размер, затем заменит [x][y] соответствующим индексом для одномерного массива с помощью простой математики: [COLS*x + y].

С другой стороны, это не относится к динамически выделенным массивам, если вам нужна та же многомерная функциональность (на самом деле нотация). Поскольку их размер может быть определен во время выполнения, они должны будут помнить размер каждого дополнительного измерения для последующего использования - и помнить об этом на протяжении всего срока службы массива. Более того, системные изменения должны были бы быть реализованы здесь, чтобы работать с массивами, фактически как многомерными, оставляя форму нотации доступа [x][y] в коде, не заменяя ее одномерной нотацией во время компиляции, но позже заменяя ее внутри во время выполнения.

Следовательно, отсутствие из array = new int[ROWS][COLS] не предполагает необходимости для delete[][] array;. И, как уже упоминалось, это не может быть использовано в вашем примере для удаления вашего «многомерного» массива, потому что ваши подмассивы (дополнительные измерения) размещаются отдельно (с помощью отдельного вызова new), поэтому они не зависят от верхний массив (array_2D), который содержит их, и все они не могут быть удалены сразу.

0 голосов
/ 14 октября 2008

Ну, я думаю, что это легко реализовать, но слишком опасно. Легко сказать, создан ли указатель с помощью new[], но трудно сказать о new[]...[] (если разрешено).

0 голосов
/ 13 октября 2008

Вы можете использовать класс-обертку, чтобы сделать все это за вас. Работа с «примитивными» типами данных обычно не является хорошим решением (массивы должны быть заключены в класс). Например, std :: vector - очень хороший пример, который делает это.

Удалить нужно вызывать точно, сколько раз вызывается новый. Поскольку вы не можете вызвать «a = new X [a] [b]», вы также не можете вызвать «delete [] [] a».

Технически это хорошее дизайнерское решение, предотвращающее появление странной инициализации всей n-мерной матрицы.

0 голосов
/ 13 октября 2008

delete [] применяется к любому нескалярному (массиву).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...