Итак, я динамически присваивал память двумерному массиву:
int **paMatrix = new int*[r];
for(int i=0; i<r; i++)
paMatrix[i] = new int[c];
Предположим, что мой код уже определен r
и c
. Теперь я хочу снова освободить память. Если paMatrix
был paMatrix
, delete[] paMatrix;
будет достаточно. Это также достаточно в этом случае, или мне нужно написать
for(int i=0; i<r; i++)
delete[] paMatrix[i];
delete[] paMatrix;
В случае, если мне нужно вызвать delete
один раз для каждого new
оператора, есть ли способ переписать мой код, так что мне нужен только один оператор delete
?
В общем, вам нужно сопоставить каждое new
с delete
поэтому, если вы здесь жёстко манипулируете целым массивом необработанных указателей, вам действительно нужно будет удалить их по очереди.
Это может быть серьезной проблемой, если код между new
и delete
не является простым, и почти невозможно гарантировать, может ли он генерировать исключения. По этой причине вы должны всегда использовать типы RAII, такие как контейнеры и интеллектуальные указатели, для управления динамическими ресурсами. В этом случае vector<vector<int>>
может быть подходящим выбором.
Я предполагаю, что реальный вопрос: "Что делает
delete
иdelete[]
действительно за сценой?"
Если тип объекта имеет нетривиальный деструктор, он вызывает деструктор на каждом объекте до освобождения памяти. Таким образом, типы RAII будут автоматически освобождать любой ресурс, который они управляют, через своего деструктора; но исходные указатели не имеют деструкторов, поэтому их удаление не освободит память, на которую они указывают.
Как уже говорилось, в c++ у одного редко бывает более одной косвенности через указатели. На самом деле, в c++ указатели избегают, когда это возможно.
В случае, если мне нужно вызвать delete один раз для каждого нового оператора, есть ли способ переписать мой код, так что мне нужен только один оператор удаления?
Один из способов:
int *paMatrix = new int[r*c];
но тогда вам нужно играть с индексами.
Еще одно решение (без указателей) без какой-либо одной инструкции delete - использовать std::vector
:
std::vector< std::vector< int > > paMatrix( r, std::vector< int >( c, 0 ) );
Как описано в других ответах здесь, вам нужно сопоставить вызовы с новыми с вызовами для удаления.
Однако, если вы захотите изменить свою концепцию массива 2d, вы можете значительно упростить ее. Например, если это действительно матрица размера rxc, вы можете выделить ее как один массив из числа r * c:
int* paMatrix = new int[r*c];
Затем вы сможете удалить его за один шаг.
Компромисс должен был бы индексировать массив, используя нечто вроде paArray[x+c*y]
вместо более естественного paArray[x][y]
.
Тебе нужно
for(int i=0; i<r; i++)
delete[] paMatrix[i];
delete[] paMatrix;
Там нет пути, кроме умных указателей и т.д.