这是超级基础但我无法在任何地方找到答案.有很多帖子在那里大约抛出和捕获,但实际发生的事情,如果我throw从function1,然后调用function1从function2,但不抓住它,这是否意味着它只是被重新抛出来的来电function2?从以下情况来看,我会说是的,但是在我开始并假设之前,我希望得到一个坚实的大师般的答案:
#include <iostream>
void function1()
{
throw 1;
}
void function2()
{
function1();
}
int main()
{
try
{
function2();
}
catch(...)
{
std::cout << "caught!";
return 0;
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Output:
caught!
Ben*_*oit 21
是的,这就是异常的工作方式.抛出异常时,它会被调用堆栈中最顶层的函数捕获,该函数在执行范围内具有该异常的处理程序.由于您将返回堆栈中较低的函数,因此上层堆栈框架中函数范围内的某些变量需要超出范围,因此会调用它们的析构函数.这称为堆栈展开.把它和RAII结合起来真是太好了(如果你不知道那是什么的话,查找RAII).但是,如果任何析构函数在堆栈展开期间抛出异常,则它很糟糕并且std::terminate将调用该函数.通常,您的程序将结束(这就是为什么总是建议您编写非抛出析构函数).
一旦构造了异常对象,控制流就会向后工作(向上调用堆栈),直到它到达try块的开始,此时将关联的catch块的参数与抛出的表达式进行比较以找到匹配.如果未找到匹配项,则控制流继续展开堆栈直到下一个try块,依此类推.如果找到匹配项,则控制流将跳转到正常执行的匹配catch块(异常处理程序).
当控制流向上移动调用堆栈时,对于所有具有自动存储持续时间的对象调用析构函数,因为以相反的构造顺序输入了相应的try-block.如果从构造函数抛出异常,则会为所有完全构造的非静态非变体成员和基类调用析构函数.此过程称为堆栈展开.
sha*_*oth 10
由于function2()并且function1()没有捕获异常,它将向上传播调用堆栈,直到它被您拥有的第一个合适的处理程序捕获main().沿着被称为堆栈展开的方式调用本地对象析构函数.如果您没有合适的处理程序,C++运行时将调用unexpected()内置函数来调用abort()和终止程序.
是的,但它没有得到"重新抛出" - 简单地说,当你抛出一个异常时,它将遍历调用堆栈,直到它找到一个catch可以处理它的块; 这是例外最重要的"卖点"之一.
如果找不到合适的处理程序,std::terminate则调用并且程序异常终止(请注意,在这种情况下,不能保证将调用析构函数).
这是否意味着它只是被重新抛出给 function2 的调用者?
不,它不会被重新抛出;原件throw根据需要将它发送到调用堆栈的最远位置,直到找到处理程序。在这种情况下,function1or 中没有处理程序function2,因此它最终位于 中的处理程序中main。
如果它根本没有被捕获,并试图离开main,那么程序将终止。(有一些方法可以改变这种行为,但这与这个问题并不是特别相关)。
| 归档时间: |
|
| 查看次数: |
17560 次 |
| 最近记录: |