[c++] OK or catch {}

Maurog

интересует вопрос, что шустрее будет работать, если анализировать корректность выполнения функции
if ( OK != myfunc
{
cout <<"\n error in myfunc";
return BAD;
}
или все же быстрее быдет выполняться
try {
myfunc
}
catch (...) {
cout <<"\n error in myfunc";
throw;
}
учитывается, что myfunc вызывается много раз в цикле и интересует даже не описание ошибки или тип или тд...а просто хочется, чтобы в случае предусмотренной ошибки (типа некоторый параметр меньше нуля, то выйти из функции и родительской сообщить, что функции не отработала корректно)
короче, если myfunc очень часто вызывается, то как оптимальнее делать проверку (чтобы прога шустрее работала):
1) анализируя OK или BAD возвращаемого значения
2) делать catch
?

daru

На vc6-7 быстрее будет обойтись без исключений. Думаю, что для большинства распространенных платформ и компиляторов это тоже будет верно.

mirt1971

Я думаю что быстрее будет catch особенно если заключить в try блок не отдельную итерацию, а весь цикл.

otvertka07

а не проще ли опытным путем это установить?

Maurog

хочешь сказать, что куча циклов
catch {
for
for
for myfunc
}
оборвется, при первом же throw из myfunc?
как-то сомнительно звучит

mirt1971

Да. Оборвется.

bleyman

Ага. Вылет эксепшена жрет время пропорциональное глубине стека (т.е. количеству вызовов функций) и количеству блоков try-catch от места выкидывания до места поимки. По-моему так. То есть в рекурсивном алгоритме эксепшены будут работать медленнее, а в случае дохуйа вложенных циклов и вообще большого количества проверок наверное быстрее. Хотя в какой именно момент эксепшены начнут рулить - хз.

Maurog

отлично
потестю завтра

mirt1971

А по моему ты не прав. Это зависит от объектов с непустыми деструкторами, расположенными в стеке. Если их нет - то стек сворачивается одной командой Те неважно, рекурсия или не рекурсия... И вообще, exceptions всегда должны рулить. Так как проверка происходит всегда, а раскрутка стека - только тогда когда действительно что-то случилось.

olegusmaximus

оборвется все до нужного catch

mira-bella

в идеале (т.е. для хорошего компилятора, каковых в природе нет) быстрее работает с исключениями, поскольку исключение ни в коем случае не ловится внутри цикла (а вот проверка возврата ошибки осуществляется именно внутри цикла).
Исключение ловится только в одном месте - в функции main в других функциях оно только генерируется в случае ошибки (ну кроме тех случаев когда вы хотите обрабатывать нефатальные ошибки без выхода из програмы - тогда конечно эти "нефатальные" исключения можно словить в том месте, которое и должно их обработать)
Например:
#include <exception>
#include <iostream>
int main(void)
{
try
{
// Весь код программы
...............................
...............................
}
catch(std::exception& Ex_)
{
std::cerr<<"error: "<<Ex_.str<<'\n';
return 1;
}
return 0;
}
Вообще это не вопрос производительности, а вопрос стиля: при написании програм в стиле C++ возврат ошибок не используется НИКОГДА - только исключения. Почему? Потому, что проверка ошибок, кроме того что занимает время выполнения програмы (что несущественно еще загромождает текст програмы, делая его менее читабельным, дублируя одни и те же обработки ошибок многократно в каждом месте, где вызывается функция их возвращающая.
Возврат ошибок - это стиль языка C, который для C++ является устаревшим.

mirt1971

Полностью согласен.

bleyman

гм. А я не согласен. Дело в том, что ексепшен - это реально исключительная ситуация, которая вообще-то случаться не должна. Если все хорошо. Поэтому я категорически не согласен с тем, например, как в шарпе работает int Int.Parse(string). Который кидает эксепшен, если не удалось пропарсить. Причем у некоторых классов есть еще <type> TryParse(string, out bool success) (не помню точно а у некоторых нету, причем особенно удивляет меня то, что TryParse реализован через вызов Parse а не наоборот. Если учесть смешные тормоза при прокидывании самого первого эксепшена в проге, то становится как-то неприятно.
Ну то есть это я к тому, что некоторые функции типа FindSomething вполне могут возвращать нулл в случае неудачи. Дабы не множит сущности. Эксепшены это, конечно, хорошо, но их вовсе не для того придумали чтобы возвращать значение функции =)

Maurog

>>Вообще это не вопрос производительности, а вопрос стиля:
мне на стиль очень наплевать, ибо когда прога работает больше недели, то стоит призадуматься о производительности, а не о стиле (хотя бы в некоторых моментах)
а вообще, очень нелогично использовать исключительную ситуацию в качестве кода возврата из функции, но если это очень шустро реализовано, то этим можно воспользоваться
насчет "стиль языка C, который для C++ является устаревшим" тут тоже могу не согласиться, ибо функции всегда возвращают и будут возвращать значения ибо это фундаментальный смысл функций, заимствованный из си. А что делать с этим значением-это уже дело каждого
И если бы разработчики компиляторов сообразили, как шустро делать исключения, вместо возврата 0 или 1, то был бы им респект. А пока я рассматриваю си++ как простую надстройку над си, вытаскивающую си из низкоуровневого языка программирования , которая лишь тормозит всю исполняемую часть, зато придает ей логичность и некоторую осмысленую формулировку, в которой так нуждаются любители высокоуровневого прогр-ния

psihodog

ну ты очень и очень не прав, что так делаешь

bleyman

Не факт. Я тут почитал Гради Буча, про Объектно Ориентированный Дизайн. Он примеры пишет в основном на плюсах. В результате я понял, что плюсов не знаю, на самом деле. Я знаю не очень сложно объектно-ориентированный С с разными приятными шняжками типа оверлоаднутых операторов. И это прекрасно! Потому что если бы я знал С++ _полностью_, то это бы выебало мне моск тоже полностью.
С полной отчетливостью я понял это после такого примера.


class InternalElectricalData: private ElectricalData {
public:
InternalElectricalData(float v1, float v2, float a1, float a2);
virtual ~InternalElectricalData;
ElectricalData::currentPower;
};

freezer

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

evgen5555

Виртуальный деструктор - это говеная маза.

rosali

Вообще-то int не может быть null Меня как раз наоборот бесит C-ная atoi, которая возвращает 0, и когда действительно 0, и когда строка из букв, тупизм.

rosali

ибо функции всегда возвращают и будут возвращать значения ибо это фундаментальный смысл функций

Вот именно, значения, а не коды ошибок. Что приятнее


f(g(h(x;


или


int err;
t1 y;
err = h(x,&y);
if(err != 0) return err;
t2 z;
err = g(y,&z);
/*и т д*/


короче, риторический вопрос...
Кстати, даже не только в эстетизме дело. Во втором случае пришлось явно написать t1,t2,... и значит их труднее будет заменить на другие. По моему огромный недостаток C++, что нельзя объявлять переменную, тип которой компилятор выведет сам исходя из начального значения, приходится всякие typedef идиотские сочинять в классах, очень удобно

rosali

Виртуальный деструктор - это говеная маза.

Ума не приложу, к чему ты это сказал... Не понимаешь зачем нужен виртуальный деструктор? Не смог ни разу грамотно им воспользоваться?
PS. Шаблоны, виртуальное наследование, мульти наследование, копирующий конструктор, рекурсия - говеные мазы

bleyman

ыыы. А как ты без него удалишь объект, когда ты уже давно забыл какого он на самом деле типа? Заведешь виртуальную функцию Дестрой, которая будет вызывать деструктор своего объекта? гы гы гы.
Бтв, меня заставил недоумевать не виртуальный деструктор =)

otvertka07

а что не так то?

Marinavo_0507

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

bleyman

class InternalElectricalData: private ElectricalData
{
public:
InternalElectricalData(float v1, float v2, float a1, float a2);
virtual ~InternalElectricalData;
ElectricalData::currentPower;
};
Не, я понимаю, что я плюсов не знаю...
2Гадфазер - а типа мб они организуются и убьют Страуструпа?

FRider

Не, я понимаю, что я плюсов не знаю...
2Гадфазер - а типа мб они организуются и убьют Страуструпа?

А мазовая идея.... давно пора

sever7777

>Не, я понимаю, что я плюсов не знаю...
о, я теперь понимаю от чего тебе стало так хорошо при переходе с плюсов на c#

bleyman

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

Russula

нужен Range Checking - юзай Vec

rosali


class InternalElectricalData: private ElectricalData
{
public:
InternalElectricalData(float v1, float v2, float a1, float a2);
virtual ~InternalElectricalData;
ElectricalData::currentPower;
};

Это всего лишь означает, что поле currentPower было в классе ElectricalData protected, а в InternalElectricalData его вынесли в public.
Или оно было public и в ElectricalData, но из-за private наследования перестало быть.
PS. Из-за теких глупостей С++ хаять, я в шоке

bleyman

Не, я это понял естественно. После того как прочитал еще немножко в книжке.
Но _выглядит_ эта строчка крайне чудовищно. Неортогонально, вот!
Оставить комментарий
Имя или ник:
Комментарий: