шпиён wrote:С первого взгляда кажется просто. 1) Лишняя аллокация/деаллокация памяти. Да еще и лик может быть, если из catch своё исключение бросится до delete. 2) Лишнее копи-конструирование, что для приведенного в примере exep не хуже копирования указателя в случае 1, но для больших/сложных классов может быть дорого. На мой взгляд, метод 2 однозначно лучше, т.к. за расчет на высокую скорость обработки исключений надо anyway бить лопатой по голове.
похоже на правду. Вот только в случае использования варианта c указателем видится мне в приведенном коде ошибка одна... Выплывет она не обязательно, но в общем, при использовании SEH есть вероятность что выплывет. Какая?
tchicago wrote:Вот только в случае использования варианта c указателем видится мне в приведенном коде ошибка одна... Выплывет она не обязательно, но в общем, при использовании SEH есть вероятность что выплывет. Какая?
Поскольку пользователь может создать класс нового exception exep_new на основе базового класса exep и при этом catch operator сработает также, однако delete операция вызовет деструктор базового класса. Ещё один пример, когда лучше объявить деструктор виртуальным в базовом классе
class exep
{
public:
exep(int err) : _error(err) {}
virtual ~exep() {}
int get_code() const { return _error; }
private:
int _error;
};
The philosophy of one century is the common sense of the next. --Henry Ward Beecher
tchicago wrote: Вот только в случае использования варианта c указателем видится мне в приведенном коде ошибка одна...
ИМХО, если при создании объекта через new чтото произойдет, то я не уверен, что catch поймает исключение.
Вы имеете в виду создание через new самого объекта exception?
То есть программа кинет exception в момент создания объекта exception.
В таком случае я не вижу разницы и в том и в другом случае catch не сработает, поскольку это будет другой тип exception.
The philosophy of one century is the common sense of the next. --Henry Ward Beecher
roadman wrote:Поскольку пользователь может создать класс нового exception exep_new на основе базового класса exep и при этом catch operator сработает также, однако delete операция вызовет деструктор базового класса. Ещё один пример, когда лучше объявить деструктор виртуальным в базовом классе
Не совсем понимаю, почему это "еще один" пример. Виртуальный деструктор, с формальной точки зрения, нужен тогда и только тогда, когда объект класса удаляется вот таким вот полиморфным образом. Так что это не "еще один" пример. Это просто очередная вариация одного и того же примера.
AndreyT wrote:Не совсем понимаю, почему это "еще один" пример. Виртуальный деструктор, с формальной точки зрения, нужен тогда и только тогда, когда объект класса удаляется вот таким вот полиморфным образом. Так что это не "еще один" пример. Это просто очередная вариация одного и того же примера.
Поскольку SomeLibraryClass подразумевает дальнейшее наследование, то вполне возможно, что автор унаследованного класса захочет определить и свои исключения. Они будут унаследованы от исключений, используемых данным классом, чтобы базовый класс мог их корректно обрабатывать. Не определив виртуальный деструктор для базового исключения мы таким образом запрещаем потомку exep иметь свой деструктор. А если потомок его определит, и будет надеяться, что он будет вызван - looming disaster.
tchicago wrote: Поскольку SomeLibraryClass подразумевает дальнейшее наследование, то вполне возможно, что автор унаследованного класса захочет определить и свои исключения. Они будут унаследованы от исключений, используемых данным классом, чтобы базовый класс мог их корректно обрабатывать. Не определив виртуальный деструктор для базового исключения мы таким образом запрещаем потомку exep иметь свой деструктор. А если потомок его определит, и будет надеяться, что он будет вызван - looming disaster.
Поэтому бросать и ловить исключение по указателю - изврат.
Инлайновых, которые копируют только указатель на VMT (и, может быть, неколько байт доп. инфо)? По сравнению с отведением и освобождением памяти на куче?
И самое главное - зачем? Уж не думаете ли Вы, что обработка исключения сравнима с копированием нескольких байт? И её стоит иметь в performance-critical потоке исполнения? И тем более в комплекте с аллокациями-деаллокациями?
Инлайновых, которые копируют только указатель на VMT (и, может быть, неколько байт доп. инфо)? По сравнению с отведением и освобождением памяти на куче?
И самое главное - зачем? Уж не думаете ли Вы, что обработка исключения сравнима с копированием нескольких байт? И её стоит иметь в performance-critical потоке исполнения? И тем более в комплекте с аллокациями-деаллокациями?
Зависит от:
a) Сложности объекта исключения. Во многих случаях это не просто несколько байт памяти.
б) Архитектуры приложения/библиотеки. Некоторые библитеки действительно используют механизм исключений для доставки пользователю результатов работы (с точки зрения разработчика библиотеки это исключительная ситуация, с точки зрения ее пользователя - нет)
в) Наличия собственного аллокатора памяти или свойств стандартного.
Инлайновых, которые копируют только указатель на VMT (и, может быть, неколько байт доп. инфо)? По сравнению с отведением и освобождением памяти на куче?
И самое главное - зачем? Уж не думаете ли Вы, что обработка исключения сравнима с копированием нескольких байт? И её стоит иметь в performance-critical потоке исполнения? И тем более в комплекте с аллокациями-деаллокациями?
Зависит от:
a) Сложности объекта исключения. Во многих случаях это не просто несколько байт памяти. б) Архитектуры приложения/библиотеки. Некоторые библитеки действительно используют механизм исключений для доставки пользователю результатов работы (с точки зрения разработчика библиотеки это исключительная ситуация, с точки зрения ее пользователя - нет)
А причем тут производительность? При таких условиях о ней УЖЕ мечтать не приходится.
tchicago wrote:в) Наличия собственного аллокатора памяти или свойств стандартного.
Вам известны аллокаторы, производительность которых (на new И на delete) сравнима с отсутсвием аллокации?