Здравствуйте, lpd, Вы писали:
lpd>Ты представляешь сколько тактов занимает сравнение кода возврата в регистре с кодом успеха? lpd>Для прикладного кода да, исключения подходят. Но иногда(например, real-time код) необходимо понимать их ограничения по скорости.
Ты про серебряную пулю?) Такого не бывает. С помощью С++ ясен пень можно и плохо сделать при желании. Исключения легко существуют с возвратом bool. Но как только количество кодов возврата превышает количество флагов (к примеру в char, int — или где хранятся) — производительность исключений вне вопросов.
А для real-time там своя специфика — но это не отменяет того, что стоимость использования исключений вне его можно принимать за ноль.
Здравствуйте, smeeld, Вы писали:
S>Мля, Вы не понимаете, всё то, что Вы говорите, похоже на теоретическую воду. Причин отказа от фишек С++ могут быть сколько угодно. Вот у нас функция, инициализирующая ряд ресурсов, чтоб не писать простыню, пишем ряд функций для инициализации каждого ресурса и вызываем их по порядку. В каждой инициализация может окончиться ошибкой, но в этом случае не нужно откатываться куда-то дальше этой функции, а просто передать ей другие параметры и вызвать снова. Как ловить ошибку в каждой такой функции, считывать код возврата или кидать в ней исключение? Первое будет производительней, особенно если эта инициализирующая ресурсы функция вызывается несколько десятков тысяч раз в секунду, это, например, сервер, обрабатывающий запросы. Если использовать исключения, будем десятки тысяч раз в секунду нырять в throw. Оно надо? Лучше вернуть код возрата, тем более если там возврат может быть только true или false. Так же и с инициализацией, объекты создаются и уничтожаются тысячами в секунду, инициализировать их с init/create-и смотреть на возврат-простое эффективное решение, чем пихать всё в конструктор, проверяться исключениями, постоянно делать is_good, объекту. S> Короче, теоретически C++-ные вещи выглядят красиво, но на практике, особенно если речь идёт об исполнении проги в агрессивных условиях исполнения, эти вещи часто превращается просто в уродство, и нужно, как бегущему легкоатлету нужно болтающееся конское седло между ног. Ядро ОС исполняется в агрессивной среде, агрессия идёт со стороны железа, прикладных прог, приходящих извне данных, там С++-ные фишки будут жутко мешать, они только всё усложняют, потому С++ в ядра с намордником не пускают
Вы пытаетесь показать, что с помощью С++ если постараться, то можно сделать плохо? Не нужно, все мы в курсе этого. Тут все ошибки в одном месте: успешность инициализации не зависит от объекта, ситуация не является исключительной (штатная, раз можно перезапустить функцию с другими параметрами при неудаче), неудача не содержит информации (true/false). Пытаться всё это завернуть в RAII — это как попытка натянуть сову на глобус. Это не RAII проблема.
Pzz>Это, я полагаю, теоретическое построение, да?
Pzz>Symmetric cone NAT вряд ли выдержит десятки тысяч попыток установления соединения в секунду. Просто таблицы переполнятся, и дальше будет плохо. Собственно, обычные домашние роутеры зачастую не выдерживают и нескольких десятков попыток в минуту, просто зависают к чертовой матери.
Нет, у нас, например, редиректящий екстернальный сигнальный сервер, он получает соединение, и редиректит его другим хостам за натом, внешние адреса которых меняется постоянно, и он постоянно получает периодические уведомления о текущих адресах каждого хоста за натом, которые в состоянии online для некоторой p2p сети. Всё по TCP, понятно дело, ибо шифроваться нужно.
Здравствуйте, okman, Вы писали:
O>1. Работа такая. O>2. Какое это имеет отношение к обсуждаемому вопросу? O>3. Какое это имеет отношение к обсуждаемому вопросу?
Чтобы дать адресный совет, очевидно. Если ты наемный кодер, то тебе бесполезно советовать взять clojure и написать на нем адаптивный кодогенератор, менеджер заругает.
O>У меня набор callback-функций, предоставляемых операционной системой, которые O>срабатывают при наступлении определенных событий. Открыли устройство — сработал один callback. O>Закрыли — сработал другой. И т.д. В этих callback-функциях происходит создание различных O>ресурсов, работа с ними и удаление. Управлять тем, чтобы ресурсы создавались где-то в одном O>месте и в одном потоке, я не могу.
Можете, типичный паттерн registry. Потоки не выделяют ресурсы сами, а обращаются к registry и уже он выделяет ресурс и смотрит кому что выдано. После смерти потока/устройства/whatever registry проверяет выданные ресурсы и прибирает все что забыли удалить явно. Для этого достаточно только сдизайнить вменяемый life cycle ваших ресурсов и определить что для вас unit of work. Я надеюсь готовить ООП на чистом С вы умеете?
O>Review не дает гарантию, что все ссылки во всех ветках выполнения были освобождены.
Если вам нужна строгая гарантия, вам нужно смотреть в сторону автоматической верификации. Но, скорее всего, ревью вам вполне хватит. Недостаточно одинарного ревью, сделайте тройное.
O>Мечтаю увидеть, как пишутся драйверы и прочий системный низкоуровневый код на Python/Clojure/etc.
Пишутся, и еще как: готовится модель, описывается на любом языке с минимальным синтаксисом (Clojure, Scheme, Lisp, Ruby), из этой модели делается кодогенерация в С. Бывает что кодогенерацию делают прямо в реалтайме, с учетом внешнего окружения.
Здравствуйте, okman, Вы писали:
O>Здравствуйте, lpd, Вы писали:
lpd>>shared_ptr неудобен и все равно нужно в некоторых местах использовать weak_ptr из-за кольцевых ссылок, что только усложняет дело.
O>Shared_ptr в любом случае лучше, чем управление ссылками "вручную". O>А кольцевые ссылки — это проблема совсем другого уровня, чем утечка ссылок.
Во-первых, shared_ptr громоздок. Если современный C++-way состоит в том, чтобы везде использовать умные указатели и забыть про проблемы с памятью, то почему не сделать "Type ^ptr" или "smart Type *" для умного указателя вместо вырвиглазного шаблона shared_ptr<Type> ptr?
Во-вторых, забыть про проблемы не получится, т.к. по прежнему нужно вникать в детали управления памятью и использовать в ряде случаев weak_ptr. И именно эта проблема — основная, поскольку банально забыть free сложно, а диагностировать тривиальную утечку легко с помощью valgrind или аналогичных средств.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, pestis, Вы писали:
P>Если ты наемный кодер, то тебе бесполезно советовать взять clojure и написать на нем адаптивный кодогенератор, менеджер заругает. P>... P>готовится модель, описывается на любом языке с минимальным синтаксисом (Clojure, Scheme, Lisp, Ruby), из этой модели делается кодогенерация в С. Бывает что кодогенерацию делают прямо в реалтайме, с учетом внешнего окружения.
Т.е. предлагается решать проблемы C, используя Clojure, Scheme и другие языки?
Мне это не подходит, проще тогда сразу писать на них, а не на C.
P>Можете, типичный паттерн registry. Потоки не выделяют ресурсы сами, а обращаются к registry и уже он выделяет ресурс и смотрит кому что выдано. После смерти потока/устройства/whatever registry проверяет выданные ресурсы и прибирает все что забыли удалить явно. Для этого достаточно только сдизайнить вменяемый life cycle ваших ресурсов и определить что для вас unit of work. Я надеюсь готовить ООП на чистом С вы умеете?
Во-первых, при таком подходе все снова сведется к тому, что кто-то должен будет в нужных точках
вызывать нужные методы registry, чтобы тот подчищал выданные ресурсы. Получаем все ту же проблему,
только в несколько ином виде.
Во-вторых, время жизни объекта не всегда может совпадать со временем жизни потока, устройства или
чего-то еще. Доступ к объекту может потребоваться намного после того, как соответствующий файл
был закрыт (например, для сбора статистики).
Здравствуйте, lpd, Вы писали:
lpd>Во-первых, shared_ptr громоздок.
Более громоздок, чем 100500 free/cleanup/delete по всему коду?
lpd>Во-вторых, забыть про проблемы не получится, т.к. по прежнему нужно вникать в детали управления памятью и использовать в ряде случаев weak_ptr. И именно эта проблема — основная...
Ну в моем примере, например, циклические ссылки невозможны, потому что объекты не
ссылаются друг на друга.
lpd>...поскольку банально забыть free сложно... lpd>...а диагностировать тривиальную утечку легко с помощью valgrind или аналогичных средств.
Здравствуйте, okman, Вы писали:
O>Здравствуйте, lpd, Вы писали:
lpd>>Во-первых, shared_ptr громоздок.
O>Более громоздок, чем 100500 free/cleanup/delete по всему коду?
Если delete написан явно, то это код читабельный и прозрачный. В случае shared_ptr все равно нужно учитывать время жизни объекта.
И не раскрыт вопрос, почему не сделали для него нормальный синтаксис.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
PD>>Компилировать в Debug. Для Release Error code time будет просто 0, так как компилятор выкинет весь этот код с вызовом функции. Выкинуть код с исключением он не может.
PD>>Так что не надо заявлять, что обработка исключений столь уже дешева. Это все же вызов ядра (throw в VC++ вызывает RaiseException) _NN>Давай правильно сравнивать. _NN>Кинуть исключение дороже чем вернуть значение, с этим никто не спорит. _NN>Однако, исключения это исключительная ситуация, а посему это должно быть редким явлением.
_NN>А теперь сравним именно такой код:
<skipped>
Ну писал же я чуть выше — компилировать в Debug, потому что Release просто выкинет код. Нет же, не верят. Ладно
Компилируем твой код в Release, ставим брекпойнт и смотрим disassembly
dwTimeStart = GetTickCount();
0038102B mov ebx,dword ptr ds:[382000h]
00381031 mov edi,5F5E100h
00381036 mov dword ptr [count],edi
00381039 call ebx
0038103B mov esi,eax
for (int i = 0; i < count; i++)
{
int result = ErrorCodeFunction(count);
}
dwTimeEnd = GetTickCount();
0038103D call ebx
printf("Error code time = %d\n", dwTimeEnd - dwTimeStart);
0038103F sub eax,esi
00381041 push eax
00381042 push 382118h
00381047 call dword ptr ds:[382098h]
0038104D add esp,8
call ebx — это и есть вызов GetTickCount. А между этими двумя вызовами стоит одна команда mov esi,eax. Вот ее время выполнения ты и замерил
_NN>Release: _NN>Error code time = 0 _NN>Try catch time = 0
_NN>Увеличим количество итераций: int count = 100*1000*1000; _NN>Release: _NN>Error code time = 47 _NN>Try catch time = 62
А вот здесь у меня соответственно 0 и 217. Время выполнения команды команды mov esi,eax не изменилось
_NN>Получаем разницу 15ms/10*1000*1000 = 1.5ns.
Здравствуйте, push, Вы писали:
P>Вы либо пытаетесь ввести в заблуждение, либо не до конца понимаете оптимизацию в с++. Тут даже без компиляции очевидно, что код с ErrorCodeFunction вырезается (и это абсолютно никак не связано с кодами возврата). В реальной функции ничего не вырезается.
Вырезается только в Release, о чем я ясно написал. Цитирую себя
PD>Компилировать в Debug. Для Release Error code time будет просто 0, так как компилятор выкинет весь этот код с вызовом функции. Выкинуть код с исключением он не может.
Поэтому я и проводил сравнения в Debug, где ничго не вырезается. Для чистоты эксперимента.
P>В случае кодов возврата вам требуется проверять код каждый раз и для каждой функции, и вне зависимости от успеха/неудачи.
Верно. Но это всего лишь одна-две команды, что по сравнению с набором команд самой функции не очень большой оверхед, если функция мало-мальски сложная. Стоит функцию чуть-чуть изменить — и мы получим на десяток или сотню команд больше или меньше. Я уж не говорю, что будет, если в функции есть хотя бы линейный цикл — в этом случае это время сравнения есть просто O(1) на фоне O(N).
Есть и еще один момент. Коды возврата можно и не анализировать, если в данной ситуации он несущественен. Например, булевская функция delete может возвращать true, если удалили и false — если нет того, что нужно удалить. Но если мне все равно (а мне может быть все равно, так как мне надо, чтобы удаляемого там больше не было, и мне не важно, нет его теперь там потому, что удалили или потому, что и не было до попытки удалить), то я могу и игнорировать код возврата. Исключение не проигнорируешь.
P>Учитывая, что количество неудач по сравнению с количеством успешного выполнения функций ничтожно мало — то и накладные расходы на исключения фактически можно считать равными нулю. И нулю не только по сравнению с кодами возврата, а вообще в принципе. Потому что, при успехе накладных расходов почти нет, а при неудаче важность потребления процессорного времени по сравнению с важностью обработки ошибки стремиться к нулю.
А вот с этим могу согласиться. Действительно, пример мой довольно искусственный — так реально не бывает. Но я лишь хотел показать, что выброс исключения сравнительно недешевая вещь. Если оно и впрямь происходит очень-очень редко, то оверхедом на него можно пренебречь. Впрочем, это верно для чего угодно при условии, что это что угодно происходит очень-очень редко (и, конечно, само не занимает много времени). Если же не очень редко — тут все будет иначе.
Я не противник исключений, отнюдь нет. Я просто хотел напомнить, что это довольно затратный механизм и об этом надо помнить.
Здравствуйте, _NN_, Вы писали:
_NN>Здравствуйте, Pavel Dvorkin, Вы писали:
_NN>Ок более приближённый тест функция верхнего уровня не оптимизируется , скажем это функция обратного вызова.
<skipped>
Что-то я этот код плохо понимаю
1. CallThrowFunction нигде не вызывается и никому не нужна
2. TestErrorCode вызывает CallErrorCodeFunction, но не анализирует результат. Поэтому имеем следующее. Вот цикл
for (int i = 0; i < count; i++)
{
result = TestErrorCode(result, count);
01081030 mov ecx,esi
01081032 call TestErrorCode (01081000h)
01081037 mov esi,eax
01081039 dec edx
0108103A jne wmain+20h (01081030h)
}
Все верно, TestErrorCode вызывется count раз
А теперь смотрим код TestErrorCode
Упс!
--- c:\users\dvorkin\documents\visual studio 2013\projects\consoleapplication8\consoleapplication8.cpp
CallErrorCodeFunction(count);
return result + 1;
01081000 lea eax,[ecx+1]
}
01081003 ret
Так что ты просто время почти пустого цикла померил.
А теперь смотрим второй цикл
for (int i = 0; i < count; i++)
{
result = TestThrow(result, count);
01081060 mov ecx,esi
01081062 call TestErrorCode (01081000h)
01081067 mov esi,eax
01081069 dec edx
0108106A jne wmain+50h (01081060h)
}
Вот тебе и раз. Компилятор почему-то решил, что здесь можно TestErrorCode вызвать вместо TestThrow. Но это не ошибка компилятора — если в TestThrow вставить printf, вызывается, как положено, TestThrow. Видимо, оптимизатор решил, что можно и ту вызвать, все равно. Может быть, потому что ErrorCodeFunction и ThrowFunction совпадают.
А пока что ты еще раз время почти пустого цикла померил. Времена совпадают
Кстати, если убрать __declspec(noinline), то оба времени равны 0, так как компилятор вообще оба цикла выбрасывает вместе со всем содержимым.
Непростая штука это оптимизатор, очень непростая
Ну а если по существу... Конечно, в зависимости от 1) как часто выполняется throw и 2) как соотносится количество команд на проверку кода возврата с количество команд в самой функции — соотношение может варьироваться в широких пределах.
Если сама функция содержит десяток команд, то дополнительные команды проверки кода возврата могут повлиять на скорость работы. Если же функция читает что-то с диска или из сети, то время для проверки кода возврата есть бесконечно малое по сравнению с временем работы функции.
Если throw происходит один раз на 100500 вызовов — его время есть бесконечно малое по сравнению с суммарным временем работы этих 100500 вызовов. Если каждые 5 раз — то может быть и сравнимо.
Так что истина конкретна.
А я всего лишь хотел показать, что собственно throw — try- catch достаточно затратная операция. А дальше — зависит от того, на фоне каких других затрат.
Здравствуйте, push, Вы писали: P>Зачем делать откат на самые начала? Зачем ловить исключение сразу после вызова функции?....
Я бы мог пройтись практически по каждому пункту твоего поста, и показать что исключения сосут у кодов возврата. Но для лулзов просто поинтересуюсь, как дела с исключениям в асинхронных коллбеках? Как там, весело выше по стеку их хендлить?
Есть ещё один момент, когда доходит дела до деталей, то оказывается что не все исключения одинаково полезны. И (цитата) "исключения необходимо бросать только в исключительных ситуациях!" Поэтому, внимание! Сейчас совсем вводящий "исключительных" программистов в ступор вопрос: как определить что ситуация "исключительная"? Ну и контрольный! Должен ли метод OpenFile бросать исключение если файл не найден? (это просто пуля, голоса "исключительных" разделились ровно поровну, началась междуусобица, разброд и шатание)
почти оффтоп
а то получается как у аджайловедов и прочих теоретиков кайфа —
----аджайл-пропоганда
Команда: А так можно делать?
Аджайл-балабол: Можно!
Команда: Но это же не совсем по аджайлу
Аджайл-балабол: В том то и дело, это же аджайл! Гибкая методология!
...
Команда: Мы тут делали аджайл и у нас не получилось
Аджайл-балабол: Вы просто не точно следовали практикам аджайла!
------исключительная пропаганда
Команда: А правда что с исключениями код будет лучше?
"Исключительный": Правда-правда. Только лучше и ничего кроме лучше!
Команда: У нас тут код с исключениями хуже чем с исключениями
"Исключительный": Ахххахаха /лалка/, тут же ситуация не-ис-клю-чи-тель-на-я !!!))))
Здравствуйте, antropolog, Вы писали:
A>Я бы мог пройтись практически по каждому пункту твоего поста, и показать что исключения сосут у кодов возврата.
C удовольствием послушаю. У меня был достаточный опыт разработки с помощью С и кодов возврата до того как перешел на С++ и исключения.
A>Но для лулзов просто поинтересуюсь, как дела с исключениям в асинхронных коллбеках? Как там, весело выше по стеку их хендлить?
Оууу, а информация о исключении нужна там? (ну то есть если не исключение, то кода возврата ты будешь выдавать выше по стеку? ) То то же и оно. Я так понимаю начинаем придумывать как сделать плохо с помощью С++? Да можно-можно, никто и не спорит, если надо что-то запороть — то при старании получится.
A>Есть ещё один момент, когда доходит дела до деталей, то оказывается что не все исключения одинаково полезны. И (цитата) "исключения необходимо бросать только в исключительных ситуациях!" Поэтому, внимание! Сейчас совсем вводящий "исключительных" программистов в ступор вопрос: как определить что ситуация "исключительная"?
Элементарно Ватсон!) Исключительная ситуация, это когда выполняются все следующие пункты:
1) её возникновение не ожидается в (нормальном) потоке выполнения
2) делает невозможным выполнение целого блока кода
3) несёт информацию о проблеме (возврат true/false — не исключительная ситуация)
A>Ну и контрольный! Должен ли метод OpenFile бросать исключение если файл не найден?
Естественно должен. Почему смотри выше. Какие исключения могут быть — смотри сюда, в один из самых лучших фреймворков: https://msdn.microsoft.com/en-us/library/b9skfh7s(v=vs.110).aspx
не плюсы, конечно, но сути не меняет.
Уж надеюсь ты не планировал сделать код возврата булевым, чтобы запороть всю инфу по проблеме?
Здравствуйте, antropolog, Вы писали:
A>Должен ли метод OpenFile бросать исключение если файл не найден? (это просто пуля, голоса "исключительных" разделились ровно поровну, началась междуусобица, разброд и шатание)
Разброд и шатание может быть только у джунов. И только потому, что они не видят что вопрос некорректный. Вопрос должен звучать так "Должен ли метод OpenFile бросать исключение?". И всё сразу становится на свои места.
Здравствуйте, push, Вы писали:
P>C удовольствием послушаю.
Я думаю в процессе обсуждения все аргументы так или иначе будут озвучены.
P>Оууу, а информация о исключении нужна там? (ну то есть если не исключение, то кода возврата ты будешь выдавать выше по стеку? )
Я код возврата выдам напрямую в параметр коллбека. А вот что будешь ты делать с исключением — пока загадка.
P>Я так понимаю начинаем придумывать как сделать плохо с помощью С++?
причём здесь C++? Я тебе говорю об асинхронных коллбеках, т.е. коллбеках которые вызываются из другого контекста ( другой тред, очередной цикл event-loop ). Ты не сможешь поставить try catch вокруг вызова, потому что он асинхронный. Это же очевидно. Где тогда ловить исключение?
P>Элементарно Ватсон!) Исключительная ситуация, это когда выполняются все следующие пункты: P>1) её возникновение не ожидается в (нормальном) потоке выполнения P>2) делает невозможным выполнение целого блока кода P>3) несёт информацию о проблеме (возврат true/false — не исключительная ситуация)
A>>Ну и контрольный! Должен ли метод OpenFile бросать исключение если файл не найден? P>Естественно должен. Почему смотри выше.
Великолепно. Осталось только узнать, как OpenFile понимает, ожидается ли возникновение ошибки клиентским кодом или не ожидается? Что если таки ожидается и я в случае ошибки беру данные из другого файла/сети/whatever? Это нормальный flow, всё ожидаемо. Но вот почему-то OpenFile бросает исключение. Почему? Почему он делает мне неудобно?
P>Уж надеюсь ты не планировал сделать код возврата булевым, чтобы запороть всю инфу по проблеме?
А никакой инфы и нет. Более того, при использовании исключений этой инфы меньше в разы всегда. Просто открой любые C++ проекты и посмотри что там ловят в catch() и что при этом делают. И на это есть объективные причины.
Здравствуйте, antropolog, Вы писали:
A>Я код возврата выдам напрямую в параметр коллбека. А вот что будешь ты делать с исключением — пока загадка.
Код возврата чего? Ты же сказал, что даешь свой коллбек асинхронному фреймворку — ну у тебя возникла проблема и куда что возвращаешь?
P>>Я так понимаю начинаем придумывать как сделать плохо с помощью С++?
A>коллбеках которые вызываются из другого контекста ( другой тред, очередной цикл event-loop ).
std::promise/std::future
A>Великолепно. Осталось только узнать, как OpenFile понимает, ожидается ли возникновение ошибки клиентским кодом или не ожидается? Это с какой такой радости он должен что-то понимать??? Такое в принципе невозможно. Он сигнализирует о проблеме, а дальше это уже проблема клиента как реагировать.
A>Что если таки ожидается и я в случае ошибки беру данные из другого файла/сети/whatever?
Ну и бери. И что?
A>Что если таки ожидается и я в случае ошибки беру данные из другого файла/сети/whatever? Это нормальный flow, всё ожидаемо.
Если в твоей проге это нормальный flow — то не бросай исключение. Я даже не буду спрашивать как так у тебя получилось, что ты хочешь взять данные из отсутствующего файла . Я же не в курсе, может у тебя всё автоматом подставляется, если нет прав — игнорируется, если нет файла — подставляется заглушка — тогда конечно, вообще и в принципе проверка наличия файла бессмысленная. Но такая логика программы всецело на твоей совести.
А в общем случае — отсутствие файла это исключение, так как его наличие должно было быть обеспечено раньше (да, в разработке принято проверять наличие чего-либо, прежде чем использовать).
A>Но вот почему-то OpenFile бросает исключение. Почему? Почему он делает мне неудобно?
Чем именно неудобно — что сказал правду об отсутствии файла?
A>А никакой инфы и нет. Более того, при использовании исключений этой инфы меньше в разы всегда. Просто открой любые C++ проекты и посмотри что там ловят в catch() и что при этом делают. И на это есть объективные причины.
Я вообще-то разрабатываю на плюсах и знаю как и что. С помощью исключений можно получить без напряга столько инфы, сколько при ручном сборе с помощью кодов возврата никогда не будет (ибо банально слишком трудоёмко). Открой для себя boost::exception. По пути раскрутки стека можно собрать практически дамп всех слоёв приложения.
Здравствуйте, push, Вы писали:
P>Здравствуйте, antropolog, Вы писали:
A>>А никакой инфы и нет. Более того, при использовании исключений этой инфы меньше в разы всегда. Просто открой любые C++ проекты и посмотри что там ловят в catch() и что при этом делают. И на это есть объективные причины. P>Я вообще-то разрабатываю на плюсах и знаю как и что. С помощью исключений можно получить без напряга столько инфы, сколько при ручном сборе с помощью кодов возврата никогда не будет (ибо банально слишком трудоёмко). Открой для себя boost::exception. По пути раскрутки стека можно собрать практически дамп всех слоёв приложения.
У механизма исклюений есть как плюсы так и минусы. Одними из минусов кроме быстродействия являются усложнение логики(и уменьшение прозрачности кода) и увеличение связности программы — когда вызывающий код должен понимать и обрабатывать данные exceptionа из вызываемого.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>А я всего лишь хотел показать, что собственно throw — try- catch достаточно затратная операция. А дальше — зависит от того, на фоне каких других затрат.
А я в свою очередь хочу показать, что отсутствие throw — try — catch не так затратно как обещают противники исключений.