这是预期的行为.从C++标准:
如果当前没有处理异常,则执行不带操作数的throw-expression调用terminate()(15.5.1).
至于为什么编译器无法诊断这一点,需要进行一些相当复杂的流程分析,我想编译器编写者不会认为它具有成本效益.C++(和其他语言)充满了可能的错误,理论上这些错误可能被编译器捕获但实际上并非如此.
这是预期的行为.从C++标准:
如果当前没有处理异常,则执行不带操作数的throw-expression调用terminate()(15.5.1).
至于为什么编译器无法诊断这一点,需要进行一些相当复杂的流程分析,我想编译器编写者不会认为它具有成本效益.C++(和其他语言)充满了可能的错误,理论上这些错误可能被编译器捕获但实际上并非如此.
详细说明尼尔的答案:
throw;
本身将尝试重新提升当前正在解除的异常 - 如果多个被解开,它会尝试重新抛出最近的异常.如果没有被解开,则调用terminate()来表示你的程序做了一些虚假的事情.
至于你的下一个问题,为什么编译器不会throw;
在catch块之外发出警告,编译器无法在编译时告诉该throw;
行是否在catch块的上下文中执行.考虑:
// you can try executing this code on [http://codepad.org/pZv9VgiX][1] #includeusing namespace std; void f() { throw 1; } void g() { // will look at int and char exceptions try { throw; } catch (int xyz){ cout << "caught int " << xyz << "\n"; } catch (char xyz){ cout << "caught char " << xyz << "\n"; } } void h() { try { f(); } catch (...) { // use g as a common exception filter g(); } } int main(){ try { h(); } catch (...) { cout << "some other exception.\n"; } }
在此程序中,g()
作为异常过滤器运行,可以从h()
可以使用此异常处理行为的任何其他函数中使用.您甚至可以想象更复杂的情况:
void attempt_recovery() { try{ // do stuff return; } catch (...) {} // throw original exception cause throw; } void do_something() { for(;;) { try { // do stuff } catch (...) { attempt_recovery(); } } }
这里,如果在do_something中发生异常,则将调用恢复代码.如果该恢复代码成功,则会忘记原始异常并重新尝试该任务.如果恢复代码失败,则忽略该故障并重新抛出先前的故障.这是有效的,因为throw;
在catch块attempt_recovery
的上下文中调用了in do_something
.
从C++标准:
15.1抛出异常
...
如果当前没有处理异常,则执行不带操作数调用的throw-exception
terminate()
编译器无法可靠地捕获此类错误的原因是异常处理程序可以调用函数/方法,因此编译器无法知道是否throw
在a中发生catch
.这基本上是一个运行时的东西.