LINUX.ORG.RU

оператор delete


0

1

есть программа которая работает с динамическим массивом.
работает она так:
int** a = new int*[n];

for(int i=0; i<nl i++)
a[i] = new int[n];

// работа с массивом

for(int i = 0; i<n; i++)
delete a[i];
delete a;

Вопрос: правильно ли очищается память? В том смысле что нужно ли писать в цикле так:
delete[] a[i];
или достаточно текущего варианта?
В отладчике смотрел оба варианта - все очищает одинаково, но дело в том что преподаватель этот вариант считает неправильным.

★★

«delete[] a;» и «delete[] a;». сам не плюсятник, но однажды на лоре обсуждалась разница, запомнилось…

arsi ★★★★★ ()

Для массива интов монопенисуально, но в общем случае надо писать delete[], так что преподаватель прав.

anonymous ()
Ответ на: комментарий от anonymous

ну так в отладчике я ведь вижу что оно и так и так очищается. те разницы ставить скобки или нет в данном случае нет

sacred ★★ ()
Ответ на: комментарий от sacred

Поставь туда какую-нибудь структуру с нетривиальным деструктором вместо инта.

anonymous ()
Ответ на: комментарий от sacred

если правильно помню, разница появится, если тип — класс с деструктором. если не ошибаюсь, new[] возвращает указатель на память, в -sizeof(size_t) относительно которого записано количество элементов, а delete[] это количество читает и вызывает для каждого элемента деструктор. вроде так.

arsi ★★★★★ ()
Ответ на: комментарий от sacred

не, ну можно вообще не вызывать delete, все равно в конце работы программы память будет возвращена системе и в данном случае все работает.

anonymous ()

Если память мне не изменяет, то delete применённый к массиву объедков удалит только первый.

KblCb ★★★★★ ()
Ответ на: комментарий от anonymous

смысл в том что препод так и сказал - что память можно не очищать, но я решил что надо сразу приучивать себя к правильному коду. А вот теперь получается что написал, что все очищается - а он говорит что неправильно

sacred ★★ ()
Ответ на: комментарий от sacred

не факт. с++ специалисты тебе расскажут точнее, но: new[] возвращает указатель не на начало выделенного участка памяти (как это делает скалярный new). поэтому не факт, что скалярный delete корректно освободит память.

arsi ★★★★★ ()
Ответ на: комментарий от sacred

> смысл в том что препод так и сказал - что память можно не очищать

Забавный преподаватель. Я бы не стал оспаривать оценку на твоем месте.

rival ★★ ()

Преподаватель прав. Массив нужно удалять ТОЛЬКО с помощью delete[]. То, что у тебя с твоим компилятором и программой случайно не вылетела ошибка - ничего не значит, скомпилируешь другим компилятором и получишь утечку памяти, например. В С++ часто бывает, что вроде программа неправильная, но работает корректно. Но это приводит к плачевным последствиям в самые неожиданные моменты.

Legioner ★★★★★ ()
Ответ на: комментарий от rival

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

sacred ★★ ()
Ответ на: комментарий от sacred

преподаватель, как ни странно, прав: в данном конкретном случае память можно не освобождать — её освободит система после смерти процесса. вот только процесс может умереть преждевременно при попытке некорректного освобождения памяти.

мораль: решил освобождать память? освобождай её правильно! :)

arsi ★★★★★ ()
Ответ на: комментарий от Reset

Если программист не может написать stl, он плохой программист. А без аллокаторов stl не напишешь.

Legioner ★★★★★ ()
Ответ на: комментарий от sacred

> те в конкретном случае можно идти и оспаривать оценку?

Верно, требовать вместо тройки - поставить двойку, и дать еще задачек, что-бы подучить язык.

hydraulicbrakefluid ()

5.3.5 Delete

The delete-expression operator destroys a most derived object (1.8) or array created by a new-expression.

delete-expression:

::opt delete cast-expression

::opt delete [ ] cast-expression

The first alternative is for non-array objects, and the second is for arrays. The operand shall have a pointer type, or a class type having a single conversion function (12.3.2) to a pointer type. The result has type void. If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion function, and the converted operand is used in place of the original operand for the remainder of this section. In either alternative, if the value of the operand of delete is the null pointer the operation has no effect. In the first alternative (delete object), the value of the operand of delete shall be a pointer to a non-array object or a pointer to a sub-object (1.8) representing a base class of such an object (clause 10). If not, the behavior is undefined. In the second alternative (delete array), the value of the operand of delete shall be the pointer value which resulted from a previous array new-expression.72) If not, the behavior is undefined. [Note: this means that the syntax of the elete-expression must match the type of the object allocated by new, not the syntax of the new-expression. ] [Note: a pointer to a const type can be the operand of a delete-expression; it is not necessary to cast away the constness (5.2.11) of the pointer expression before it is used as the operand of the delete-expression. ]

alex_custov ★★★★★ ()
Ответ на: комментарий от Booster

Где Вы С++ увидели?

А что это за язык, кстати?

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от sacred

Преподаватель прав, см. сюда: http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.13

Для Ъ:

Can I drop the [] when deleteing array of some built-in type (char, int, etc)?

No!

Sometimes programmers think that the [] in the delete[] p only exists so the compiler will call the appropriate destructors for all elements in the array. Because of this reasoning, they assume that an array of some built-in type such as char or int can be deleted without the []. E.g., they assume the following is valid code:

void userCode(int n)
 {
   char* p = new char[n];
   ...
   delete p;     // ← ERROR! Should be delete[] p !
 }

But the above code is wrong, and it can cause a disaster at runtime. In particular, the code that's called for delete p is operator delete(void*), but the code that's called for delete[] p is operator delete[](void*). The default behavior for the latter is to call the former, but users are allowed to replace the latter with a different behavior (in which case they would normally also replace the corresponding new code in operator new[](size_t)). If they replaced the delete[] code so it wasn't compatible with the delete code, and you called the wrong one (i.e., if you said delete p rather than delete[] p), you could end up with a disaster at runtime.

gizzka ★★ ()

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

const86 ★★★★★ ()
Ответ на: комментарий от Booster

Да, в этой стране все преподаватели только на D и дают задания. Очнитесь же уже!

Zloddey ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.