我们先来看一个setjmp, longjmp的简单程序:
#include <iostream>
#include <csetjmp>
using namespace std;
class A
{
public:
A()
{
cout << "constructor" << endl;
}
~A()
{
cout << "destructor" << endl;
}
};
jmp_buf xxx;
void test()
{
A a;
cout << "c++" << endl;
longjmp(xxx, 100);
}
int main()
{
int ret = setjmp(xxx);
if( 0 == ret)
{
printf("1111, ret is %d\n", ret);
test();
}
else
{
printf("2222, ret is %d\n", ret);
}
printf("3333, ret is %d\n", ret);
return 0;
}
先看看结果吧:
1111, ret is 0
constructor
c++
destructor
2222, ret is 100
3333, ret is 100
我们来看看行为非常特别的函数setjmp, 第一次调用它时, 返回0, 当longjmp跳跃时, 相当于第二次调用到setjmp, 此时返回的是longjmp传过来的值, 所以会有上述结果。 但唯一有点意外的是, 居然有destructor, 应该不会调用到析构函数啊。 原来, 这是VC++6.0编译器做了扩展, 但是, 我们要注意, 不是所有的编译器都这样(例如, 上述程序在g++中就不会调用析构函数, 请注意, 如果用g++编译, 那就还需要加上#include <cstdio>), 所以上述程序是不可移植的, 那怎么办呢? 用C++异常处理机制吧, 如下:
#include <iostream>
using namespace std;
class A
{
public:
A()
{
cout << "constructor" << endl;
}
~A()
{
cout << "destructor" << endl;
}
};
void test()
{
A a;
cout << "c++" << endl;
throw 100;
}
int main()
{
try
{
printf("1111\n");
test();
}
catch(int i)
{
printf("2222, i is %d\n", i);
}
printf("3333\n");
return 0;
}
结果为:
1111
constructor
c++
destructor
2222, i is 100
3333
此时, 析构函数肯定是要调用的, 无论在啥编译器中。
嗯, 先这样。