Comments 28
Эта функция будет вызвана ВСЕГДА, когда класс разрушается.
Во-первых, не класс, а объект класса. Во-вторых, новичкам, на которых якобы ориентирован пост, не всегда и очевидно, когда объект на самом деле «разрушается», об этом дальше.
Не важно что произошло, выход из функции посередине или даже выброшенное исключение, деструктор класса будет вызван в любом случае, пока программа работает.
Ну вот например так:
Class* object = new Class(); throw std::bad_alloc(); delete object;
Да, утечка объекта, но в тексте выше ничего не сказано о том, что речь-то идет только об автоматических переменных, а «разрушаются» они при выходе из области видимости.
На C деструктор вызывается вручную, что заставляет писать много лишних подробностей.
В C нет деструкторов.
Это Серега еще забыл рассказать про исключение-во-время-исключения и исключения в конструктрах :). У него вообще хорошо получается стандарт языка перефразировать. Неоднозначно так :)
Я не ставлю перед собой задачу пересказа распространенных книг по C++, new, delete и heap — сильно базовые вещи, чтобы на них заострять внимание.
Отсутствие классов с C запрещает использовать в этом языке ООП?
Расскажите это разработчикам, например, GTK+
Отсутствие классов с C запрещает использовать в этом языке ООП?
Расскажите это разработчикам, например, GTK+
Статья толковая.
Возможно фразу
стоит переформулировать как:
«Для справки, если исключение никто не ловит, компилятор имеет право не вызывать деструкторы, поэтому в main нужно ставить try...catch на все типы исключений.»
И еще не понятен пример с reserve у vector'а. reserve хорош для уменьшения количества переаллокаций, но как и в какой ситуации он поможет, если кинулось исключение? В каком случае код будет требовать определенного количества элементов в vector'е, но корректно работать если некоторые элементы пустые?
Возможно фразу
Для справки, программа уже не работает, если исключение никто не ловит, поэтому в main нужно ставить try...catch на все типы исключений.
стоит переформулировать как:
«Для справки, если исключение никто не ловит, компилятор имеет право не вызывать деструкторы, поэтому в main нужно ставить try...catch на все типы исключений.»
И еще не понятен пример с reserve у vector'а. reserve хорош для уменьшения количества переаллокаций, но как и в какой ситуации он поможет, если кинулось исключение? В каком случае код будет требовать определенного количества элементов в vector'е, но корректно работать если некоторые элементы пустые?
Не надо путать reserve и resize. Вызов reserve гарантирует, что в процессе серии вызовов push_back не произойдет переаллокации памяти внутри вектора. Если такая переаллокация необходима — она произойдет в момент выполнения reserve, т.е. до построения структуры данных. Следовательно исключение о нехватке памяти не оборвет процесс построения этой структуры.
Я действительно перепутал reserve и resize.
Исключение нехватки памяти не оборвет процесс построения структуры т.к. вылетит либо до, либо после вызова конструктора. Если оно вылетит после, то будет вызван деструктор и объект корректно удалится. Пока единственное преимущество, которое я вижу — в крайне маловероятном случае нехватки памяти не будет потрачено время на создание и удаление объекта.
Исключение нехватки памяти не оборвет процесс построения структуры т.к. вылетит либо до, либо после вызова конструктора. Если оно вылетит после, то будет вызван деструктор и объект корректно удалится. Пока единственное преимущество, которое я вижу — в крайне маловероятном случае нехватки памяти не будет потрачено время на создание и удаление объекта.
По мне так логгирование в деструкторе не совсем корректный вариант.
Ваш пример с вектором не состоятелен по 2 причинам:
1) Имплементация вектора в любом STL имеет запасы даже тогда, когда пользователь об этом не просил. reserve стоит использовать только в случаях, когда вы точно знаете, что вам нужно добавить много элементов и вы не хотите реаллокаций.
2) Выделив память reserve'ом Вы забываете о конструкторах элементов. В примере у Вас int, но мы же говорим в общем ;). Так что Ваши потуги с ранним reserve для сохранения нейтральности исключений вряд-ли будут плодотворны.
1) Имплементация вектора в любом STL имеет запасы даже тогда, когда пользователь об этом не просил. reserve стоит использовать только в случаях, когда вы точно знаете, что вам нужно добавить много элементов и вы не хотите реаллокаций.
2) Выделив память reserve'ом Вы забываете о конструкторах элементов. В примере у Вас int, но мы же говорим в общем ;). Так что Ваши потуги с ранним reserve для сохранения нейтральности исключений вряд-ли будут плодотворны.
reserve() не вызывает конструкторы элементов, в отличии от resize(). reserve() всего лишь заранее резервирует raw память для последующих операций.
И?
Любая реаллокация это потенциальное исключение нехватки памяти. Как гарантировать отсутствие этого исключения между двумя push_back вызовами?
А как гарантировать отсутствие исключения во время push_back(конструктор объекта)?
reserve решает проблему push_back, но не решает проблему конструктора, а значит не имеет смысла его использование в данном контексте, т.к. гарантии как не было так и нет.
reserve решает проблему push_back, но не решает проблему конструктора, а значит не имеет смысла его использование в данном контексте, т.к. гарантии как не было так и нет.
Это уже конструктор вашего объекта, тут много простора для действий. Реаллокация в контейнере — это код stl.
Плюс ко всему в последней версии C++ есть std::move.
Плюс ко всему в последней версии C++ есть std::move.
Если говорим про C++11, то там есть emplace, move тут явно не к месту.
Нет тут никакого простора, мы обсуждаем конкретную ситуацию. Нет смысла достигать нейтральности исключений тем способом, что Вы указали, т.к. она нарушается конструктором объекта помещаемого в контейнер. Другими словами, reserve применён Вами избыточно и он не гарантирует нейтральности исключений по отношению к контейнеру. Контейнер всё еще может содержать один элемент и не содержать второй.
Это уже конструктор вашего объекта, тут много простора для действий.
Нет тут никакого простора, мы обсуждаем конкретную ситуацию. Нет смысла достигать нейтральности исключений тем способом, что Вы указали, т.к. она нарушается конструктором объекта помещаемого в контейнер. Другими словами, reserve применён Вами избыточно и он не гарантирует нейтральности исключений по отношению к контейнеру. Контейнер всё еще может содержать один элемент и не содержать второй.
Вы не поверите, но писать посты в Интел никого не заставляют. Но, несмотря на это, постов так много, что они выстраиваются в очередь на публикацию (ну нельзя их всех выдавать оптом, в один день — сами понимаете, получится очень дешево). И когда до нее дело доходит, то автор зачастую оказывается вне досягаемости для ответов. Но он обязательно появится еще, причем, — в этом году. Я вам обещаю.
Как раз и интересно почему вы так забавно процесс выстроили. Мне иногда тоже приходиться заниматься продвижением в сообществах. И вот смотрю я как вы феерически сливаете карму и рейтинг, побликуя какие-то очень спорные опусы и не отвечая в комментариях — и в упор не понимаю зачем. Единственное предположение — что внук одного из руководителей рассказал ему про хабр, после чего сверху пришла отмашка «писать десять постов в месяц». Ну вы и стараетесь :).
Изначальное допущение ошибочно. Мы не занимаемся «продвижением в сообществах». А спорные опусы порой гораздо интереснее бесспорных.
Бесспорно. Но это в том случае если есть с кем данный опус обсудить. Но если автор выложил опус и не появляется в комментариях, то данный опус не является дискуссионным. Именно поэтому подобные опусы интереса не представляют. Тем более, что качество оных оставляет желать лучшего.
Мне кажется человек назвал опус спорным из чистой вежливости. Я когда дочитал до уничтожения класса смутно стал припоминать, что был некоторое время еще один похожий, в конец неграмотный пост от «крутого программиста из интел», и точно!
Блин, что за школьник у Intel Russia пишет настолько неграмотные статьи?
Реально, косяк на косяке, и не первая статья уже.
Я не пишу на C++ уже лет десять, фактически, но ляпы очевидны.
Реально, косяк на косяке, и не первая статья уже.
Я не пишу на C++ уже лет десять, фактически, но ляпы очевидны.
Интел, ну зачем вы позоритесь? Вам вот уже в двух статьях подряд половина Хабра указывает, что этот человек не знает С++ и пишет чёрти-что. Ради чего это? Ну ведь будут думать, что у вас все так пишут. У вас есть прекрасные разработчики, хороший компилятор, прекрасные библиотеки — зачем публиковать вот это?
Мне понравилась иллюстрация к посту.
Пример с перестановкой хидеров — это сильно.
Теперь я буду всегда писать static_cast вместо сишного каста.
Теперь я буду всегда писать static_cast вместо сишного каста.
Sign up to leave a comment.
Чистый С++: Как правильно разрушать