LINUX.ORG.RU

[бенчмарк] С++ медленне С в 5 раз при уже при 0.1% кидаемых исключений [ЧЯДНТ ?]


0

2

Вот исходники

#include <stdio.h>

#define BITS 10    // 0<=BITS<=16

unsigned int i0=0, i1=0;

int f(unsigned int arg)
{
    if( ( (arg>>16) & ((1<<BITS)-1) ) == 0 )
        return 1; // exception
    else
        ++i0; // do some good work here, i.e. increment i0
    return 0; // ok
}
int main()
{
    unsigned int i=0, x=1;

    do {
        ++i;
        x+=x<<2; // x == 5 power i
        if( f(x) )
            ++i1; // exception
    }
    while(x!=1);

    printf("i=%u i0=%u i1=%u i0+i1=%u\n", i,i0,i1,i0+i1 );
    printf("  %u    %u    %u       %u\n", 0x40000000u, i-i1, (1<<(16-BITS))<<14, 0x40000000u );
    return 0;
}

#include <stdio.h>

#define BITS 10    // 0<=BITS<=16

unsigned int i0=0, i1=0;
class E1 {};
E1 e1;

void f(unsigned int arg)
{
    if( ( (arg>>16) & ((1<<BITS)-1) ) == 0 )
        throw &e1;
    else
        ++i0; // do some good work here, i.e. increment i0
}
int main()
{
    unsigned int i=0, x=1;

    do {
        ++i;
        x+=x<<2; // x == 5 power i
        try{ f(x); }
        catch( E1* e ){ ++i1; }
    }
    while(x!=1);

    printf("i=%u i0=%u i1=%u i0+i1=%u\n", i,i0,i1,i0+i1 );
    printf("  %u    %u    %u       %u\n", 0x40000000u, i-i1, (1<<(16-BITS))<<14, 0x40000000u );
    return 0;
}

Вот выхлопы [ gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21) ]:

$ gcc -O3 1.c && time ./a.out 
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824
  1073741824    1072693248    1048576       1073741824

real    0m2.368s
user    0m2.256s
sys     0m0.004s

$ g++ -O3 1.cxx && time ./a.out 
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824
  1073741824    1072693248    1048576       1073741824

real    0m11.741s
user    0m10.921s
sys     0m0.008s

Кто сможет протестить на icc, других версиях gcc и других железках? Возможно, я не указал полезные опции? А дальше флейм :-)

Напомню, что это именно бенчмарк "код возварата vs. исключение" (результаты можно посчитать и без программы).

www_linux_org_ru ★★★★★
() автор топика

Эх, не зря в Google C++ Style Guide написано, что ексепшены неюзабельны.

dizza ★★★★★
()
Ответ на: комментарий от lester

> давно известно, что исключения медленно работают

в несколько тысяч раз медленнее кода возврата? не слишком ли?

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

> в несколько тысяч раз медленнее кода возврата? не слишком ли?

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

vnovouhov
()

Меня интересует почему чего-то типа SEH в gcc нет. Это какая-то принципиальная позиция?

Absurd ★★★
()
Ответ на: комментарий от www_linux_org_ru

>Напомню, что это именно бенчмарк "код возварата vs. исключение"

...что делает бенчмарк бессмысленным. То, что exceptions медленнее очевидно. И их придумали не для того, чтобы быть быстрыми.

Sectoid ★★★★★
()
Ответ на: комментарий от Sectoid

> ...что делает бенчмарк бессмысленным. То, что exceptions медленнее очевидно. И их придумали не для того, чтобы быть быстрыми.

Но не *настолько* медленными. Я утверждаю, что либо gcc исключительный тормоз, либо язык С++ кривой.

И почему тогда в яве исключения-вместо-кода-возврата работают нормально? Щас запощу пример.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

> Но не *настолько* медленными. Я утверждаю, что либо gcc исключительный тормоз, либо язык С++ кривой.

Тссс, это заговор опытных разработчиков C++... Благодаря этому их код работает в разы быстрее новичков, пытающихся писать на C++, только тсс, это великая тайна!

vnovouhov
()

class U1{
    static final int BITS=10;
    
    static int i0=0, i1=0, i=0;
    static class E1 extends Exception {};
    static E1 e1=new E1();
    
    void f(int arg) throws E1
    {
        if( ( (arg>>16) & ((1<<BITS)-1) ) == 0 )
            throw e1;
        else
            ++i0; // do some good work here, i.e. increment i0
    }
    void go()
    {
        int x=1;
    
        do {
            ++i;
            x+=x<<2; // x == 5 power i
            try{ f(x); }
            catch( E1 e ){ ++i1; }
        }
        while(x!=1);
    }
    public static void main(String[] args)
    {
        U1 test=new U1();
        test.go();
        System.out.printf("i=%d i0=%d i1=%d i0+i1=%d\n", i,i0,i1,i0+i1 );
        System.out.printf("  %d    %d    %d       %d\n", 0x40000000, i-i1, (1<<(16-BITS))<<14, 0x40000000 );
        
    }
};

$ time java -server U1
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824
  1073741824    1072693248    1048576       1073741824

real    0m4.199s
user    0m3.916s
sys     0m0.036s

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

если мне не изменяет память в роадмапе gcc есть пункт про ускорение обработки прерываний, но т.к. сейчас наверняка все силы брошены на С++0х, то скоро ожидать решения не приходится

lester ★★★★
()
Ответ на: комментарий от tailgunner

> А в чем сакральный смысл угребищного выражения "( (arg>>16) & ((1<<BITS)-1) ) == 0"? Просто любопытно.

Выражение прозрачно как стеклышко :-) старшие 16 бит берутся для того, чтобы число было послучайнее, ибо последние биты 5**i очевидно совсем не случайные. BITS регулирует процент кидаемых исключений.

Кстати, поучительно выставить везде BITS=8.

Тогда С++ сливает яве в 10 (!!!) раз, притом что кидается всего лишь 0.4% исключений.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

> А в чем сакральный смысл угребищного выражения "( (arg>>16) & ((1<<BITS)-1) ) == 0"? Просто любопытно.

Чтобы число было послучайнее и оптимизаторы не могли это вычислить или подметить закономерность и перегенерировать на этой основе JIT код.

www_linux_org_ru ★★★★★
() автор топика

Сильви просила передать:


allure ~/tmp:$uname -a
Linux allure 2.6.30.1-lu #1 SMP PREEMPT Fri Jul 3 10:01:33 MSD 2009 i686 Intel(R) Core(TM)2 Duo CPU E8400 @ 3.00GHz GenuineIntel GNU/Linux


cc4.1.2-redhat -g0 -O3 -fomit-frame-pointer -mfpmath=sse -mmmx -msse2 -march=pentium4 -fomit-frame-pointer b.c
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824                                                     
  1073741824    1072693248    1048576       1073741824                                                     
real    0m0.857s
user    0m0.850s
sys     0m0.000s

c++4.1.2-redhat -g0 -O3 -fomit-frame-pointer -mfpmath=sse -mmmx -msse2 -march=pentium4 -fomit-frame-pointer b.cpp
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824                                                        
  1073741824    1072693248    1048576       1073741824                                                        
real    0m5.033s
user    0m5.023s
sys     0m0.010s

cc-4.2.4 -mmmx -msse2 -march=pentium4 -mfpmath=sse -g0 -O3 -fomit-frame-pointer b.c
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824                                
  1073741824    1072693248    1048576       1073741824                                
real    0m0.896s
user    0m0.880s
sys     0m0.003s

 c++4.2.5 -mmmx -msse2 -march=pentium4 -mfpmath=sse -g0 -O3 -fomit-frame-pointer b.cpp
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824                                   
  1073741824    1072693248    1048576       1073741824                                   
real    0m4.998s
user    0m4.993s
sys     0m0.000s

cc-4.3.3 -mmmx -msse2 -march=pentium4 -mfpmath=sse -g0 -O3 -ftree-vectorize -fomit-frame-pointer b.c                                                                                                                                        
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824                                                                                       
  1073741824    1072693248    1048576       1073741824                                                                                       
real    0m0.870s
user    0m0.837s
sys     0m0.000s

c++4.3.3 -mmmx -msse2 -march=pentium4 -mfpmath=sse -g0 -O3 -ftree-vectorize -fomit-frame-pointer b.cpp                                                                                                                                     
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824                                                                                       
  1073741824    1072693248    1048576       1073741824                                                                                       
real    0m5.037s
user    0m5.026s
sys     0m0.000s

Intel 10.1
allure ~/tmp:$icc -O3 -fomit-frame-pointer b.c ; time ./a.out
[intelcc] /opt/intel10/bin/icc -static-intel -static-libgcc -gcc -wd593,654,869,981,1292,1572,10148,10156 -g0 -fpic -fomit-frame-pointer -xN -O3 -fomit-frame-pointer b.c
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824
  1073741824    1072693248    1048576       1073741824
real    0m6.513s
user    0m6.476s
sys     0m0.000s

allure ~/tmp:$i++ -O3 -fomit-frame-pointer b.cpp -lstdc++ ; time ./a.out
[intelcc] /opt/intel10/bin/icpc -static-intel -static-libgcc -gcc -wd593,654,869,981,1292,1572,10148,10156 -g0 -fpic -fomit-frame-pointer -xN -O3 -fomit-frame-pointer b.cpp -lstdc++
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824
  1073741824    1072693248    1048576       1073741824
real    0m12.278s
user    0m12.109s
sys     0m0.003s


Intel 11.0

allure ~/tmp:$icc -O3 -fomit-frame-pointer b.c ; time ./a.out
[intelcc] /opt/intel11/bin/icc -static-intel -static-libgcc -gcc -wd593,654,869,981,1292,1572,10148,10156 -g0 -fpic -fomit-frame-pointer -xSSE2 -O3 -fomit-frame-pointer b.c
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824
  1073741824    1072693248    1048576       1073741824
real    0m6.500s
user    0m6.466s
sys     0m0.000s

allure ~/tmp:$i++ -O3 -fomit-frame-pointer b.cpp -lstdc++ ; time ./a.out
[intelcc] /opt/intel11/bin/icpc -static-intel -static-libgcc -gcc -wd593,654,869,981,1292,1572,10148,10156 -g0 -fpic -fomit-frame-pointer -xSSE2 -O3 -fomit-frame-pointer b.cpp -lstdc++
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824
  1073741824    1072693248    1048576       1073741824
real    0m12.466s
user    0m12.459s
sys     0m0.000s

hibou ★★★★★
()
Ответ на: комментарий от hibou

> Сильви просила передать:

Интересно, что будет при BITS=8 (это 0.4% кидаемых исключений), там слив д.б. еще более страшным.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от hibou

+ ещё, тоже от Сильви:

gcc-4.4.1 -mmmx -msse2 -march=pentium4 -mfpmath=sse -g0 -floop-interchange -floop-block -floop-strip-mine -ftree-loop-distribution -O3 -ftree-vectorize -fomit-frame-pointer b.c
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824
  1073741824    1072693248    1048576       1073741824
real    0m2.650s
user    0m2.646s
sys     0m0.000s

c++4.4.1 -mmmx -msse2 -march=pentium4 -mfpmath=sse -g0 -floop-interchange -floop-block -floop-strip-mine -ftree-loop-distribution -O3 -ftree-vectorize -fomit-frame-pointer b.cpp
i=1073741824 i0=1072693248 i1=1048576 i0+i1=1073741824
  1073741824    1072693248    1048576       1073741824
real    0m5.076s
user    0m4.893s
sys     0m0.000s

hibou ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

BITS = 8

allure ~/tmp:$gcc -O3 -fomit-frame-pointer b.c ; time ./a.out
[fgcc] /usr/local/bin/cc44 -mmmx -msse2 -march=pentium4 -mfpmath=sse -g0 -floop-interchange -floop-block -floop-strip-mine -ftree-loop-distribution -O3 -ftree-vectorize -fomit-frame-pointer b.c
i=1073741824 i0=1069547520 i1=4194304 i0+i1=1073741824
  1073741824    1069547520    4194304       1073741824

real    0m2.711s
user    0m2.710s
sys     0m0.000s
allure ~/tmp:$g++ -O3 -fomit-frame-pointer b.cpp ; time ./a.out
[fgcc] /usr/local/bin/c++44 -mmmx -msse2 -march=pentium4 -mfpmath=sse -g0 -floop-interchange -floop-block -floop-strip-mine -ftree-loop-distribution -O3 -ftree-vectorize -fomit-frame-pointer b.cpp
i=1073741824 i0=1069547520 i1=4194304 i0+i1=1073741824
  1073741824    1069547520    4194304       1073741824

real    0m13.545s
user    0m13.326s
sys     0m0.010s
allure ~/tmp:$icc -O3 -fomit-frame-pointer b.c ; time ./a.out
[intelcc] /opt/intel11/bin/icc -static-intel -static-libgcc -gcc -wd593,654,869,981,1292,1572,10148,10156 -g0 -fpic -fomit-frame-pointer -xSSE2 -O3 -fomit-frame-pointer b.c
i=1073741824 i0=1069547520 i1=4194304 i0+i1=1073741824
  1073741824    1069547520    4194304       1073741824

real    0m3.258s
user    0m3.256s
sys     0m0.000s
allure ~/tmp:$i++ -O3 -fomit-frame-pointer b.cpp -lstdc++ ; time ./a.out
[intelcc] /opt/intel11/bin/icpc -static-intel -static-libgcc -gcc -wd593,654,869,981,1292,1572,10148,10156 -g0 -fpic -fomit-frame-pointer -xSSE2 -O3 -fomit-frame-pointer b.cpp -lstdc++
i=1073741824 i0=1069547520 i1=4194304 i0+i1=1073741824
  1073741824    1069547520    4194304       1073741824

real    0m24.492s
user    0m24.252s
sys     0m0.010s

hibou ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

пример кода для Intel C/C++ вообще неудачный, производительность ниже и в C варианте тоже.

Sylvia ★★★★★
()

Если кто захочет тестить яву, то текст надо сложить в файл U1.java и

javac U1.java && time java -server U1

У джавы BITS=3 (а это 12% исключений) дает всего 1.5 кратное отставание от BITS=10 (0.1% исключений).

Ну и что мы получаем? При 0.4% случаев кидания исключениями уже пользоваться фактически нельзя -- и можно ли говорить после этого, что в С++ исключения есть?

А так же -- действительно ли С++ приемник С? Или требуется что-то другое?

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

> А так же -- действительно ли С++ приемник С? Или требуется что-то другое?

не путайте язык и реализацию

lester ★★★★
()

Тут желающим открывается прекрасная возможность доказать, что их python/php/... быстрее С++ (если пользоваться исключениями конечно). В случае BITS=1 или 0 шансы для этого есть. Возможно, вам удасться сделать это и при других значениях.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от lester

> не путайте язык и реализацию

Пожелание хорошее. Однако возникает вопрос: а действительно ли это проблема реализации, или исключения из плюсов кривы и не могут быть быстрее реализованы при разумных затратах сил?

З.Ы. в яве немного другие исключения

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от lester

> не путайте язык и реализацию

а вообще мне бы хотелось язык в стиле/духе с++ без таких вот явных дефектов реалиции, если это и правда они.

www_linux_org_ru ★★★★★
() автор топика

Какой-то ерундой вы тут занимаетесь. Эксепшены - для другого. Иногда они незаменимы.

dave ★★★★★
()
Ответ на: комментарий от smh

> А в чем смысл этого "бенчмарка"?

В каком стиле писать -- в стиле проверки кодов возврата или стиле кидания исключений? Все согласны, что стиль кидания исключений яснее, и кроме того (в яве при поддержке компилятора) позволяет проверить, что ни один из случаев (который бы сопровождался кодом возврата "ошибка") не забыт быть проверенным.

Но бенчмарк показывает, с++ поддерживает стиль кидания исключения с такими ограничениями, которые я бы счел неприемлемыми. Фактически этот стиль (как мы видим обоснованно) запрещают. Таким образом, выходит, что очень неутешительно, что ява язык более высокого уровня, чем с++.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

> Все согласны, что стиль кидания исключений яснее

есть такое невежественное быдло как я, которое не согласно :)

lester ★★★★
()
Ответ на: комментарий от dave

> Какой-то ерундой вы тут занимаетесь. Эксепшены - для другого. Иногда они незаменимы.

Я не предлагаю выкинуть эксепшены из плюсов. Я предполагаю, что хорошие эксепшены должны как минимум не отставать от явовских, и что времени для их оптимизации (10-15 лет) было достаточно.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от vnovouhov

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

fail. научитесь, наконец, различать ошибочные и исключительные ситуации. и посмотрите на condition'ы из CL:

http://gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts...

jtootf ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

>хорошие эксепшены должны как минимум не отставать от явовских, и что времени для их оптимизации (10-15 лет) было достаточно

согласен по всем пунктам

jtootf ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> Но бенчмарк показывает, с++ поддерживает стиль кидания исключения с такими ограничениями, которые я бы счел неприемлемыми.

Я вообще в принципе за исключения и готов заплатить временем за более наглядный код. :-) Конечно, если время выполнения не критично. С другой стороны, исключения, по идее, все-таки не так часто должны появляться.

> Фактически этот стиль (как мы видим обоснованно) запрещают.

Если что-то появляется на регулярной основе - это уже не исключительная ситуация, и её нужно как-то обрабатывать (не исключениями), это по крайней мере частично объясняет, почему такой стиль не рекомендуют.

smh ★★★
()
Ответ на: комментарий от jtootf

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

> fail.

win

> наконец, различать ошибочные и исключительные ситуации.и посмотрите на condition'ы из CL:

fail. Причем тут Лисп вообще?

tailgunner ★★★★★
()
Ответ на: комментарий от www_linux_org_ru

> Я предполагаю, что хорошие эксепшены должны как минимум не отставать от явовских, и что времени для их оптимизации (10-15 лет) было достаточно.

Спорно. В данном случае у явы есть преимущество: GC. Скорее всего, там эксепшены будут быстрее всегда. Си-пи-пишный же компилятор должен вставить разный код для удаления как созданных так еще и несозданных (создаваемых) объектов плюс проверки. На мой взгляд нет шансов догнать.

dave ★★★★★
()
Ответ на: комментарий от dave

> На мой взгляд нет шансов догнать.

Так это и *означает*, что язык кривой.

Тем не менее, я считаю, что догнать можно.

Пример: рассмотрим сишные коды возврата -- они должны быть проверены ровно в вызывающей функции, а не где-то-раньше-по-стэку. Можно ввести подкласс класса Exception, который бы соответствовал *именно* таким исключениям, и обрабатывать их *эффективно*.

Вопрос с исключениями общего вида можно тоже решить, но сложнее, примерно как regions & region inference решает вопрос с указателями.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от dave

> Си-пи-пишный же компилятор должен вставить разный код для удаления как созданных так еще и несозданных (создаваемых) объектов плюс проверки.

Ссылку можно?

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

Как работает обработка исключений в С++ хорошо описано, например, в книге Герба Саттера "Решение сложных задач на C++". Там не все так просто как кажется.

В яве же многое упрощается. Если не брать в расчет remoting, то нужно просто создать новый объект исключения и раскрутить стек. Все ненужное удалит GC потом сам! Более того, базовая безопасность автоматически гарантирована (см. определение в этой книге или в другой "Стандарты программирования на C++"). В C++ же эту безопасность нужно еще гарантировать вручную. В общем, в C++ дофига заморочек.

Нужно просто понимать, что стандартные (типовые) решения на C++ нередко оказываются менее эффективными, чем на той же яве. Именно _стандартные_ решения. Потому что, ту же явовскую виртуальную машину реализуют на C/C++, но это уже нестандартное, нетиповое решение.

Еще один пример, когда _стандартное_ си-пи-пишное решение нередко хуже явовского. Реализация строки std::string в некоторых задачах ведет себя хуже, чем java.lang.String. Более того, в яве две строки: String и StringBuffer, что более правильно с точки зрения дизайна.

Так что, нет ничего необычного в том, что си-пи-пишное решение уступает явовскому. Это - нормально. Везде есть свои плюсы и минусы.

dave ★★★★★
()
Ответ на: комментарий от smh

> Если что-то появляется на регулярной основе - это уже не исключительная ситуация, и её нужно как-то обрабатывать (не исключениями), это по крайней мере частично объясняет, почему такой стиль не рекомендуют.

0.4% это не слишком частая ситуация.

Как показал питон, это отличный инструмент с использованием которого может быть построена даже стандартная библиотека. Одно другому не мешает.

true_admin ★★★★★
()
Ответ на: комментарий от dave

> Нужно просто понимать, что стандартные (типовые) решения на C++ нередко оказываются менее эффективными, чем на той же яве.

И *по идее* это должно хотя бы компенсироваться тем, что кастомарные плюсовые решения оказываются эффективнее явовских, например, аллокация в пуле памяти и деаллокация целого пула в плюсах.

Но *где* кастомарное скоростное плюсовое решение в данном случае?

( Чтобы его было проще представить, допустим, что main -- функция обработки файла, f -- функция обработки строки файла, x -- это отдельная строка файла, ( (arg>>16) & ((1<<BITS)-1) ) == 0 это случай, когда строка файла не распарсилась, ++i0 это обработка распарсенной строки, ++i1 это обработка нераспарсенной строки )

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от dave

> Реализация строки std::string в некоторых задачах ведет себя хуже, чем java.lang.String.

std::string сливает не только яве.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

> Но *где* кастомарное скоростное плюсовое решение в данном случае?

В с++0х возможно, например, передавать в f замыкание, захватившее какие-то переменные из main и внутри f выполнять его вместо кидания исключения. Но думаю есть варианты получше/более общие.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от www_linux_org_ru

> Но *где* кастомарное скоростное плюсовое решение в данном случае?

Наверное, не использовать объекты и эксепшены из самих плюсов ;-)

В этом смысле, чистый Си выглядит более полным что-ли и законченным. Его решения не порождают обычно неэффективностей.

dave ★★★★★
()
Ответ на: комментарий от dave

> В этом смысле, чистый Си выглядит более полным что-ли и законченным. Его решения не порождают обычно неэффективностей.

Да? Вспомним хотя бы то, что sort не инлайнит compare.

Так и тут. f должна быть параметризована хотя бы одним куском кода, исполняющемся в контексте функции, вызывающей f (т.е. main). Как на С сделать такое эффективно? Передать указатель? На что??? Вложенных функций у нас в С99 нет!

www_linux_org_ru ★★★★★
() автор топика

Я допустил некоторую неаккуратность: i1 следовало определить внутри main. Но с другой стороны, это зависит от вопроса "а что мы моделируем", и ответ могут быть разные.

www_linux_org_ru ★★★★★
() автор топика
Ответ на: комментарий от tailgunner

>Причем тут Лисп вообще?

ни при чём. речь конкретно о модели conditional'ов из CL. была бы такая шняга реализована в Haskell или Erlang - привёл бы пример оттуда

>win

источник цитаты можно?

jtootf ★★★★★
()

не припомню ни одного раза, когда использовал исключения

а жаба - это да, пример "глобальности и надёжности"

PayableOnDeath
()
Ответ на: комментарий от jtootf

>>win

>источник цитаты можно?

Я не собирался цитировать, но если ты настаиваешь... %)

Б.Страуструп "Язык программирования C++", Москва, "Бином", с. 428

<Ъ> Всегда, когда это возможно, следует придерживаться точки зрения "обработка исключений является обработкой ошибок" </Ъ>

tailgunner ★★★★★
()
Ответ на: комментарий от tailgunner

><Ъ> Всегда, когда это возможно, следует придерживаться точки зрения "обработка исключений является обработкой ошибок" </Ъ>

теперь-то я точно знаю, за что не люблю Страуструпа!

jtootf ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.