C++嵌套catch中抛出是否合法?(2)处throw会触发std::terminate吗?
问题解答
代码示例
try { fun1(); } catch (...) { try { fun2(); } catch (...) { throw; // 2. 传播fun2()可能抛出的异常 } throw; // 1. 传播fun1()可能抛出的异常 }
1. 第(2)处的throw是否会触发std::terminate?
不会。
根据cppreference的说明(翻译后):
如果任何由栈展开机制直接调用的函数(在异常对象初始化后、异常处理程序开始前)抛出异常,会调用
std::terminate。这类函数包括:自动存储期对象的析构函数(当它们的作用域被退出时),以及为初始化按值捕获的参数而调用的异常对象拷贝构造函数(如果未被省略)。
第(2)处的throw处于fun2()的catch块中:此时处理fun1()异常的栈展开已经完成(已经进入了外层的catch块),当前是在处理fun2()抛出的新异常。这个throw是重抛fun2()的异常,属于正常的异常处理流程,并不符合上述触发std::terminate的条件。
2. 嵌套try/catch块中进行异常重抛是否合理?
这取决于具体场景,并非绝对不合理:
- 合理场景:当处理第一个异常时,需要执行一些可能抛出异常的操作(比如资源清理、状态恢复),这时候嵌套
try/catch可以区分处理原异常和新操作抛出的异常。比如示例代码中,在处理fun1()的异常时调用fun2()(可能是清理函数),如果fun2()抛异常就重抛它,否则重抛原异常,这种逻辑是合理的。 - 需要避免的情况:如果过度嵌套或逻辑混乱,会导致代码可读性变差,难以追踪异常流。此时应该考虑重构代码,比如将清理逻辑封装成独立函数,或者使用RAII机制减少手动异常处理的复杂度。
内容的提问来源于stack exchange,提问作者Lorah Attkins
相关产品推荐
相关产品推荐

