LINUX.ORG.RU

Деструкторы не нужны (?)

 


0

5

Тут в соседней теме один анон сказанул следующее:

Дело не в том. Сишка, она про написание руками + можно навесит абстракций, аки глиб/гобджект. Кресты же — изначально нагромождение абстракций со строками, срущими в кучу, функциональными объектами, методами, вызывающимися неявно (например, деструкторы, на которые жаловался кармак) и проч

Собственно, хотелось бы поговорить о выделенном.

Антон прикрылся ссылкой, по которой про деструкторы я так ничего и не нашёл. Более того, в твиттере Кармака всё выглядит с точностью до наоборот — https://twitter.com/id_aa_carmack/status/172340532419375104

RAII constructor / destructor pairing and templates for type safe collections are pretty high on my list of C++ benefits over C

Кто прав? Кто виноват? И нужны ли в итоге C++ деструкторы?

Уж что в крестах нужное и годное — так это деструкторы. По всей видимости, ничего лучше RAII в области управления ресурсами пока не придумали.

Softwayer ★★
()

И нужны ли в итоге C++ деструкторы?

Например, когда GCC переходил на С++, основным аргументом «за» было наличие деструкторов

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

а царевна говорил, что все это вранье и «нет там никакого цпп»

anonymous
()

Не знаю. Я так и не осилил C++. Слишком сложно для моего разгильдяйсткого ума.
Но про деструкторы точно помню, что в C++ они не просто нужны, а необходимы.

trupanka
()

На деструкторы, может быть, и можно жаловаться, но они определённо нужны.

intelfx ★★★★★
()

И нужны ли в итоге C++ деструкторы?

Вообще какой-то странный вопрос, в том посте вроде ничего не было про ненужность деструкторов. У тебя в жизни все радикально, если отвертки не подходят для забивания гвоздей, они не нужны? Тебе лет 15?

anonymous
()

Нужны. Они резко уменьшают шансы забыть освободить память, например

XMs ★★★★★
()

Очень странный вопрос. Память освобождать, файловые дескрипторы закрывать тоже не надо?

Deleted
()

Любителям goto clean_mem; не нужны. Нормальный людям - нужны.

RazrFalcon ★★★★★
()

В C++ деструкторы были бы не нужны если бы там изначально был GC, но его, к счастью, не было)

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

Тут скорее вопрос о том, нужно ли это делать неявно (при помощи деструкторов) или явно (вызывая в коде free, close и т.п.).

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

Деструкторы и GC - взаимно противоречащие вещи. Для деструкторов важен порядок их вызова (сначала для объекта, потом для его членов), а для GC порядок освобождения памяти - нет. Разница видна в случае циклических зависимостей: GC сразу может весь цикл освободить, а корректного порядка вызова деструкторов не существует.

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

Во многих языках с GC есть финализаторы. Хотя использовать их обычно является плохой идеей.

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

корректного порядка вызова деструкторов не существует.

Это как?

Как минимум в C++ порядок вызова деструкторов описан.

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

Это как?

Простой пример циклической зависимости: два shared_ptr зависят друг от друга.

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

Уж что в крестах нужное и годное — так это деструкторы.

Они, насколько я помню, очень загадочным способом с исключениями взаимодействуют. В смысле, что будет, если в деструкторе исключение? Например, файл не смог закрыться.

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

Ничего загадочного.

Во всех стандартах выбрасывание исключения из деструктора могло привести к вызову std::terminate в случае stack unwinding'а.

Начиная с C++11, деструкторы по умолчанию ещё и как noexcept помечаться стали.

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

Начиная с C++11, деструкторы по умолчанию ещё и как noexcept помечаться стали.

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

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

В C++ никто на Close / Shutdown / whatever исключения обычно не кидает.

http://www.cplusplus.com/reference/fstream/fstream/close/ :

Any exception thrown by an internal operation is caught by the function and rethrown after closing the file. It throws an exception of member type failure if the function fails (setting the failbit state flag) and member exceptions was set to throw for that state.

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

У тебя есть идеи, как более адекватно обрабатывать исключения в деструкторах?

В рамках RAII — наверное, нет. В рамках GC+finalizer — поток, в котором выполняются финализаторы вполне нормально может обрабатывать исключения (хотя бы в журнал складывать).

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

Это если ты сам того явно захочешь.

std::ifstream file;
file.exceptions(ifstream::failbit);
b0r3d0m
() автор топика
Ответ на: комментарий от monk

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

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

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

Смотря как напишешь. На SIGKILL и деструкторы не вызовутся, а на SIGTERM вполне нормально, если все потоки, кроме управляющего финализацией завершатся, запустится сборщик мусора (создаст в числе всего прочего очередь на финализацию), отработает финализация на всём в очереди и программа завершится.

У финализаторов только один минус: не определён порядок. Если тебе принципиально, чтобы файлы закрывались именно в заданном порядке, то либо явно закрывать, либо какой-то аналог RAII.

Ну речь-то о деструкторах

Так и я про то же. Деструкторы пишутся на C++ без исключений. Причём, если программист ошибся, то просто падает программа (хотя это для C и C++ практически стандарт).

В принципе, можно всегда заворачивать тело деструктора в try. А в обработчике куда-нибудь писать факт ошибки.

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

хотя бы в журнал складывать

Это не особо лучше игнорирования. Да и в рамках RAII/плюсов никто не мешает ловить исключение в деструкторе и логировать.

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

если ты не умеешь в кресты, всё именно так и произойдёт. если умеешь — вокруг каждого будет своя raii-обёртка.

anonymous
()

В чем смысл этой темы? Ведь их не уберут завтра оттуда.

Я как Qt-шник не вижу смысла жизни без деструкторов, не представляю как бы всё нормально и удобно работало без них.

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

Не знаю. Я так и не осилил C++. Слишком сложно для моего разгильдяйсткого ума.

Попытка не пытка. Я бы хотел освоить.

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

Они, насколько я помню, очень загадочным способом с исключениями взаимодействуют

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

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

Эти претензии насчёт того, что нельзя кидать исключения из деструкторов на уровне «stl не позволяет наследоваться от вектора».

На вопрос «зачем тебе это и какого поведения ты этим хочешь добиться» слышно только невнятное мычание.

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

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

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

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

Да и в рамках RAII/плюсов никто не мешает ловить исключение в деструкторе и логировать.

Тогда про логированиие должен знать сам деструктор. Ну или делать свои «исключения на коленке» в виде try { ... } catch (e) { MyException.save(e); }. А затем { MyException m; /* при создании создаёт очередь, в деструкторе обрабатывает всё, что насобиралось */ class1 c1; class2 c2; ... }

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

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

А в C++ можно добавить метод serialize() не наследуясь?

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

Почему ты отвечаешь вопросом на вопрос? Ты антисемит?

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

Не понимаю. Ты хочешь перегрузить функцию serialize(), чтобы она могла сериализовать векторы? Так наследоваться от него зачем?

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

и Dudraug. Ладно. Допустим, вы никак не представляете себе сериализацию без того, чтобы запихать в сам сериализуемый тип метод serialize().

Тогда у меня вопрос: как выглядит в этом «ООП-brain-damaged-стиле» сериализация примитивных типов, вроде int? Как от него отнаследоваться и реализовать метод serialize()?

utf8nowhere ★★★
()

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

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

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

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

во время обработки одного другое исключение еще не обработано, а значит что-то еще может находиться в сломанном виде

то ценность подобной штуки очень сомнительна ИМХО

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