Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Кодт, Вы писали:
А>Спасибо за ответы, но посмотрел внимательнее А>и увидил несоответствие вызовов деструкторов А>
Вы вставьте еще печать в конструкторе и копи-конструкторе A, и увидите что к чему.
Запись A a(99) приводит к созданию 1-го локального объекта, а s1.push(a) — к созданию его копии в контейнере. Объект a убивается при его выходе из области видимости, а его копия в контейнере — в момент s1.pop() или смерти контейнера s1
Re[4]: std:stack вызов деструктора
От:
Аноним
Дата:
23.06.08 13:52
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:
АШ>А вы расширьте интерфейс вашего класса и ответ станет очевиден:
Помимо того, что уже сказали, добавлю что в каждой из выделенных строк возможна утечка. Если при переаллокации памяти в push вылетит исключение, то утекет добавляемый объект. Как вариант, лечится так:
Здравствуйте, Юрий Жмеренецкий, Вы писали:
Если при переаллокации памяти в push вылетит исключение, то утечет добавляемый объект. Как вариант, лечится так: ЮЖ>
a.get() передаст владение до того как push_back займется переаллокацией,
так что в этом случае auto_ptr никак на поможет при броске исключения,
нужен boost::shared_ptr.
Интересно, а boost::scoped_ptr можно ли тут использовить.
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Юрий Жмеренецкий, Вы писали: А> Если при переаллокации памяти в push вылетит исключение, то утечет добавляемый объект. Как вариант, лечится так: ЮЖ>>
А>Простите может я чего не понимаю, но в строке А>
s2.push_back(a.get());
А>a.get() передаст владение до того как push_back займется переаллокацией, А>так что в этом случае auto_ptr никак на поможет при броске исключения, А>нужен boost::shared_ptr. А>Интересно, а boost::scoped_ptr можно ли тут использовить.
Ошибка в рассуждениях в том, что "get передает владение" — это не так. Владение передает release().
Следовательно, если будет выброшено исключение автоматический объект a заберет память выделенную под A1 и ничего криминального не произойдет. Если исключение выброшено не будет, то a сложит с себя обязанности по уничтожению вызовом a.release().
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, Юрий Жмеренецкий, Вы писали: А> Если при переаллокации памяти в push вылетит исключение, то утечет добавляемый объект. Как вариант, лечится так: ЮЖ>>
А>Простите может я чего не понимаю, но в строке А>
s2.push_back(a.get());
А>a.get() передаст владение до того как push_back займется переаллокацией,
get не передает владение
А>так что в этом случае auto_ptr никак на поможет при броске исключения,
Поможет, поскольку при возникновении исключения release не будет вызван, сл-но std::auto_ptr останется владельцем объекта у удалит его в деструкторе.
А>нужен boost::shared_ptr.
s2.push(boost::shared_ptr<A>(new A(88));
boost::shared_ptr решает эту проблему потому что:
Он будет сконструирован до переаллокации(ref_count = 1). При успешном завершении push ref_count будет равен 2. Потом будет удален временный объект, ref_count = 1 и объект останется жив(сохранили ссылку). При исключении увеличения счетчика ссылок не произойдет(так и будет равен еденице), соответственно в деструкторе временного объекта он достигнет 0 и объект будет удален.
Вот в этой строке:
boost::shared_ptr<A> p(new A());
существует подобная проблема, но она решается в конструкторе shared_ptr: После выделения памяти под А будет выделена пямять под счетчик ссылок, но в случае возникновения исключения, указатель(параметр конструктора) будет принудительно удален.
Т.е. выглядит это приблизительно так:
для "нормальной" работы с "голыми" указателями push должен выглядедеть приблизительно так же, либо его вызов надо оборачивать в try/cacth или иным способом гарантировать удаление(std::auto_ptr) при возникновении исключения.