[英]Why is my exception still being thrown after being caught?
我有以下代码,其中一个变量正在使用函数调用的结果进行初始化。 这个函数抛出所以我设置了一个try-catch来捕获异常。 由于某种原因,即使在catch子句运行后,异常仍会出现在屏幕上。
#include <iostream>
#include <stdexcept>
int f() { throw std::invalid_argument("threw"); return 50; }
struct S
{
S()
try : r(f())
{
std::cout << "works";
}
catch(const std::invalid_argument&)
{
std::cout << "fails";
}
int r;
};
int main()
{
S s;
}
显示异常后,此代码打印“失败”:
terminate called after throwing an instance of 'std::invalid_argument' what(): threw
为什么异常仍然被抛出? 我在main中设置了相同的代码,它可以正常工作:
int main()
{
try { throw std::invalid_argument("blah"); }
catch(const std::invalid_argument&) { }
}
那么为什么它在初始化列表中使用时会失败呢?
具有函数try块的构造函数(就像你对S
所拥有的那样)会自动重新抛出catch
块捕获的任何异常。 因此,在后catch
捕获该异常,它重新抛出它。 此行为与正常的catch
处理程序不同,后者不执行此操作。 我认为基本原理是,如果构造数据成员或基类失败,则该对象无法构造。 catch
处理程序的目的只是在异常向外传播之前进行任何额外的清理。
希望这可以帮助!
从C ++ 11标准,15.3 / 15:
如果控制到达构造函数或析构函数的function-try-block的处理程序的末尾,则重新抛出当前处理的异常。
原因在你的问题下的GOTW Jerry链接中得到了很好的解释,但是简单地说:想象一下如果它没有重新生成,那么S s;
之后的下一行S s;
尽管它从未完成构造,但可能会尝试使用s
,并且当s
离开作用域时,构造函数将安排对析构函数调用s
- 可能释放从未初始化的指针,释放永不占用的锁等。
相比之下,如果你让数据成员默认初始化然后从构造函数体中的try / catch块分配给它,那么包括基础和数据成员在内的对象的状态可能会保持在某种连贯的状态:它是up作为程序员决定该状态是否正常 - 即您是否将在构造函数体内使用try / catch块,并让后面的成员函数处理潜在的默认构造数据成员。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.