LINUX.ORG.RU

Я познаю C++. А что, оператор delete не обнуляет указатель?

 , ,


0

4

Всегда думал, что конструкция:

delete obj;

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

А оно походу совсем не таг.

★★★★★

А почему ты думал, что должен был?

Harald ★★★★★
()

А оно походу совсем не таг.

Триацилглицерид?

Zhbert ★★★★★
()

А схрена должны тратиться драгоценные циклы процессора на обнуление указателя?

Pavval ★★★★★
()

С пробуждением.

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

что должно по вашему было бы стать с foo?

Ничего. obj бы стал NULL, так как мы его delete. А foo как указывал на кусок памяти, так и указывает.

Xintrea ★★★★★
() автор топика

Это же сишка, она специально спроектирована так, чтобы ты почаще ошибался.

amomymous ★★★
()
Ответ на: комментарий от no-such-file

экономия на спичках, тяжелое наследие С

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

Это C(++) тут ничего само собой не происходит.

Разве что объекты преобразуются из типа в тип и обратно, но это такой пустяк!

staseg ★★★★★
()

Первый вопрос: «free(ptr) обнуляет ptr?»

Второй вопрос: «зачем вообще в C++ использовать delete?»

i-rinat ★★★★★
()

Обнулить указатель чтоб его проверить на NULL?! Зачем?

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

Чтобы при повторном delete небыло сегфолта, например.

А зачем ты вызваешь повторный delete? Наоборот, сегфолт - это хорошо, так ты сразу узнаешь, что программа у тебя неправильно написана и надо её исправить

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

explicit конструктор в помощь. Конечно это не спасёт от того кода, который не твой :}

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

Жабакодерам дальше по коридору :3

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

Появление повторного delete - признак кривой архитектуры.

Вот у меня сейчас программист пишет программу, которая гоняет байты по сети и ещё кое-что с ними делает. Есть небольшой класс-менеджер, который всё это заводит и соединяет вместе. В принципе, его функции можно было бы оставить главному окну программы, ну западло нам было мешать логику и GUI.

Так вот, в первой версии этот менеджер создавался при начале обработки и уничтожался при её остановке. С одной стороны логично, с другой - как раз надо проверять, то ли объект есть, то ли его нет. Поэтому сейчас менеджер создаёся вместе с главным окном и уничтожается вместе с ним. А для запуска-остановки сделали отдельные методы start() и stop(). Проблемы больше нет.

Я не отрицаю, что бывают ситуации, когда объект создаётся и уничтожается в произвольном порядке, неоднократно, но такие ситуации куда более редки, чем может показаться. И да, в таких случаях незазорно руками обнулить указатель.

Ну и насколько я помню, в Delphi free тоже не обнулял указатель :)

hobbit ★★★★★
()
Последнее исправление: hobbit (всего исправлений: 2)

Всегда думал

ЯП работают не так как ты думаешь, а так как их сделали, доки внимательно читай

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

Появление повторного delete - признак кривой архитектуры.

не парься, он гоняет нотпад++ в вайне, ибо всё остальное под линухом его категорически не устраивает, по-ходу с С++ та-же история

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

Разве что объекты преобразуются из типа в тип и обратно, но это такой пустяк!

Если мы назовём тебя «горшком» ты можешь стать им стать, а можешь и не стать.

Вот тебе набор байт, пусть это будет struct A, а теперь пусть это будет int или whatever. Где тут автоматика?

beastie ★★★★★
()
Ответ на: комментарий от i-rinat

free - функция стандартной библиотеки. В принципе ничего не мешает даже написать её самому. Она полностью равноправна с обычными функциями. И поэтому она не может обнулить указатель, который ей передали. Ну либо это должна быть не free(void *ptr), а free(void **ptr) и вызывать её придётся иначе.

А delete это оператор языка. И он вполне может напрямую взаимодействовать с переменной, в том числе обнулять её. То что там тот же free вызывается - особенность реализации компилятора.

KivApple ★★★★★
()
Последнее исправление: KivApple (всего исправлений: 1)
Ответ на: комментарий от KivApple

Ох, я как-то не задумывался до этого, но ведь delete можно перегрузить.

не free(void *ptr), а free(void **ptr)

free(void *&ptr)

i-rinat ★★★★★
()
Ответ на: комментарий от KivApple

А delete это оператор языка. И он вполне может напрямую взаимодействовать с переменной, в том числе обнулять её. То что там тот же free вызывается - особенность реализации компилятора.

Не может, указатель передаётся по значению. А ещё delete можно переопределить в своей программе, но и это не поможет обнулить переменную

Harald ★★★★★
()

Пиши на Qt... А то тебя удивит что при ошибки выделения памяти тоже не NULL, и что компилятор не обнуляет в NULL такие объявления типа obj* test; C++ боль

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от Pavval

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

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

Ничего. obj бы стал NULL, так как мы его delete. А foo как указывал на кусок памяти, так и указывает.

А если так:

char* obj = new char[100];
char* foo = obj;
delete foo;
andreyu ★★★★★
()
Ответ на: комментарий от beastie

Я как-то словил баг из-за сравнения знакового и беззнакового. Интересный опыт.

i-rinat ★★★★★
()

Впринципе, тебе уже все сказали. Кратко подитожу и чуточку от себя добавлю.
1. С++ не делает того, что тебе может не понадобится. По умолчанию приоритет номер 1 - скорость выполнения программы, а значит минимум лишних операций.
2. Ты можешь сделать так, чтобы обнулял - см. перегрузка операторов. Но я бы не советовал.
3. Зачем тебе могло понадобиться делать new и delete? При использовании stl количество кейсов для new/delete падает раз в 100. За одно отсекаешь проблемы с утечками памяти, двойным освобождением и т. п.
4. Если уж таки нужен new/delete, то делай new в конструкторе, delete в деструкторе.

P. S. И, если уж взялся за C++, используй православный nullptr.

Kroz ★★★★★
()

А напомните-ка мне зачем в 2015 году вызывать delete, если есть RAII, std::array и unique_ptr/shared_ptr?

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

Не надо делать повторный delete. Используй delete в деструкторах.

Именно так я и делаю.

Но delete в деструкторах не спасает от повторного удаления объекта, если указатель на него есть в двух разных классах.

У меня есть класс общей коллекции объектов, и класс по работе с одним активным объектом.

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

Если сделать delete в другой последовательности, то сегфолт останется по обратной причине.

Вот сейчас думаю, как выкрутится из этой ситуации.

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

Но delete в деструкторах не спасает от повторного удаления объекта, если указатель на него есть в двух разных классах.

Либо используй умные указатели либо не используй таких странных конструкций.

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

Да не, все проще, это я ступил.

Нет никакого смысла удалять объект в веркере. Ведь этот веркер работает с разными объектами, на которые он натравлен. И указатель в нем - всего лишь указатель на объект, с которым происходит работа. Объект должен удаляться в деструкторе коллекции объектов.

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

Конечно логика именно такова, но справедливости ради стоит заметить что в большинстве случаев оптимизатор мог бы стереть эту операцию.

В те года еще не было модно полагаться на оптимизации кода.

Которая обычно ничтожна по сравнению с самим delete.

Далеко не во всех применениях С++.

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

2015
школота не слышала про hpc

anonymous
()

с++
А оно походу совсем не таг

Ухаха. Сделал мой день. Интересно, что ты скажешь про виртуальный деструктор

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

Не может, указатель передаётся по значению

Внезапно, оператор может менять свой операнд.

anonymous
()

Забавно слышать такое от человека, чьей программой на C++ я пользуюсь.

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

Но delete в деструкторах не спасает от повторного удаления объекта, если указатель на него есть в двух разных классах.

Тут надо разобраться с тем, кто владеет объектом. Кто владеет, тот и удаляет.

Если оба или более владеют равноправно — использовать shared_ptr.

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