Dec 28

goto, setjmp/longjmp, try-catch 不指定

felix021 @ 2009-12-28 15:48 [IT » 程序设计] 评论(2) , 引用(0) , 阅读(7643) | Via 本站原创 | |
注:本文只是简单介绍这三个东西并对比一下其功能、差异,不讨论这些东西是否有存在的必要以及优劣。
· goto
· setjmp, longjmp
· try-catch

一、看看基本的使用
1. goto
这个比较简单,比较容易理解,只要设置一个行标就行了:
例子:
int main ()
{
    int i = 0, sum;
    for (i = 0; i < 100; ++i) {
        sum += i;
        if (sum > 1000) goto JMP1;
    }
JMP1:
    printf("%d\n", i);
    return 0;
}


2. setjmp, longjmp
goto用起来是简单,但是存在一个先天缺陷:只能在同一个函数内使用。
有时候我们写一个代码,有两三层的函数嵌套,想要返回的时候就比较囧。
这时候用setjmp和longjmp就很happy。
例子:
#include <setjmp.h>
jmp_buf jmpbuf1;

void bar() {
    printf("Hi, I'm bar!\n");
    longjmp(jmpbuf1, 1);
}

void foo() {
    printf("Hi, I'm foo!\n");
    bar();
    printf("Should never come here\n");
}

int main ()
{
    int i = 0;
    i = setjmp(jmpbuf1);
    if (i == 0) { //setjmp第一次某个jmp_buf的时候返回0
        foo();
    }
    else { //否则返回longjmp给出的值
        printf("i = %d\n", i);
    }
    return 0;
}

输出是:
Hi, I'm foo!
Hi, I'm bar!
i = 1

3. try-catch (在这里算是歪用了,呵呵)
这个是c++提供的语言特性,可以用于捕获throw语句抛出的异常,不仅可以在函数内使用,也可以跨函数~~
例子:
void bar() {
    printf("Hi, I'm bar!\n");
    throw 1;                                                                    
}

void foo() {
    printf("Hi, I'm foo!\n");
    bar();
    printf("Should never come here\n");
}

int main ()
{
    try{
        foo();
    }  
    catch(int i) {
        printf("i = %d\n", i);
    }  
    return 0;
}

输出是:
Hi, I'm foo!
Hi, I'm bar!
i = 1


二、简单对比一下:
· goto,使用简单方便,看起来比其他两个更容易一点(有行标),但是只能在函数内跳转;
· setjmp和longjmp,稍微麻烦点,需要带个参数(jmp_buf,全局变量,或者传参),好处是可以跨函数跳转,且可以根据setjmp的返回值得知从何处跳转。还有一个小缺陷就是,因为需要先执行setjmp以后才可以跳转,所以可以跳转的地方有一定限制,也使得代码看起来有点不够清晰。
· try-catch,C++有C没有,看起来结构比较清晰,不需要带额外的参数,抛出不同的值(和类型)方便判断来源。

三、重点考察一个问题:
如果有一个class,比如
class T
{
    public:
        ~T() { printf("I'm dead >_<\n"); }
};
那么使用goto、setjmp或try-catch的时候是否存在问题?

    if (1) {
        T t1;
        goto JMP1;
    }
JMP1: ;
有输出I'm dead >_<
    jmp_buf jmpbuf1;
    if (setjmp(jmpbuf1) == 0) {
        T t1;                                                                  
        longjmp(jmpbuf1, 1);
    }  
    else {
        ;  
    }  
无输出
    try {
        T t1;                                                                  
        throw 1;
    }
    catch(int i) {
        ;
    }
有输出I'm dead >_<

所以在使用这三个东西的时候,一定要特别注意,建议在C++里头不使用setjmp,以免查错无门...



欢迎扫码关注:




转载请注明出自 ,如是转载文则注明原出处,谢谢:)
RSS订阅地址: https://www.felix021.com/blog/feed.php
realdodo Homepage
2009-12-30 13:48
c++的try catch就是用setjmp来实现的,而且try catch就是为了避免调用这几个函数而设计的,因此c++中当然不要使用喽~
felix021 回复于 2009-12-30 14:28
明白了~~
sandy
2009-12-28 22:39
这不是Effective C++(还是C++Primer来着?)被经常拿来对比的例子么。。setjmp/longjmp在大多数情况下会让代码变得极为恐怖。。
felix021 回复于 2009-12-28 22:42
sweat 很少看到setjmp的使用。从C++的角度看来,的确不应该用;但是不知道在C项目中用得多不多。
分页: 1/1 第一页 1 最后页
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   *非必须
网址   电邮   [注册]