c++ 可否同时抛出两个异常
在 C++ 中,如果我们抛出异常后 ,在捕获异常之前,会析构掉所有还在堆栈上的对象。
#include <iostream>
using namespace std;
class Object {
public:
~Object();
};
Object::~Object() { cout << "Deconstructor is invoked." << endl; }
void foo() {
try {
Object obj;
throw invalid_argument("only for testing");
}catch(const exception & e) {
cout << "catch exception: " << e.what() << endl;
}
}
int main(int argc, char *argv[])
{
foo();
return 0;
}
这个时候,程序的输出是
Deconstructor is invoked.
catch exception: only for testing
这里只有一层函数调用,如果有多层函数调用,也是类似的。
#include <iostream>
using namespace std;
class Object {
public:
Object(int value) : value_(value){};
~Object();
int value_;
};
Object::~Object() {
cout << "Deconstructor is invoked. value=" << value_ << endl;
}
void foo3() { throw invalid_argument("only for testing"); }
void foo2() {
auto object = Object(2);
foo3();
}
void foo1() {
auto object = Object(1);
foo2();
}
int main(int argc, char *argv[])
{
try {
foo1();
}catch(const exception & e) {
cout << "catch exception: " << e.what() << endl;
}
return 0;
}
程序输出结果是
Deconstructor is invoked. value=2
Deconstructor is invoked. value=1
catch exception: only for testing
可以看到,堆栈上的所有对象都被析构掉了。调用析构函数的顺序和调用构造函数的顺序相反。也就是说,堆栈上的对象按照被构造的顺序,反序析构。
什么叫做“同时抛出两个异常” ? 在上面的例子中,如果我们在析构函数中再抛出一个异常,这样在捕获异常之前,就会同时存在两个异常。
#include <iostream>
using namespace std;
class Object {
public:
~Object();
};
Object::~Object() {
cout << "Deconstructor is invoked." << endl;
throw invalid_argument("another exception");
}
void foo() {
try {
Object obj;
throw invalid_argument("only for testing");
}catch(const exception & e) {
cout << "catch exception: " << e.what() << endl;
}
}
int main(int argc, char *argv[])
{
foo();
return 0;
}
在 C++ 中,如果像这样同时存在两个异常,那么程序会调用 std::terminate
,程序异常退出。
上面的例子中,输出结果是
Deconstructor is invoked.
libc++abi.dylib: terminating with uncaught exception of type std::invalid_argument: another exception
于是,不要在析构函数里面抛出异常。