C++中返回语句的拷贝构造函数异常是否会被函数内try-catch捕获?
C++返回值拷贝构造异常的捕获规则解析
可以保证异常被f内的catch捕获,而非抛至调用点,这是C++17及后续标准明确规定的行为。
标准依据
根据C++17标准(N4659)的[stmt.return]章节:
当return语句返回一个表达式时,该表达式的求值以及将其结果初始化到返回值对象的操作,都属于该return语句所在函数的执行上下文。如果这个初始化过程(包括可能的拷贝/移动构造)抛出异常,那么异常会在当前函数的范围内抛出,而非传递到调用者。
关于两个疑惑的解释
- 与函数参数拷贝异常的区别:函数参数的拷贝构造是在调用者的执行上下文中完成的——调用者负责将实参拷贝到形参,所以这个过程抛出的异常会在调用点处理;而返回值的初始化(包括拷贝/移动)是在被调用函数的执行上下文中完成的,属于return语句执行逻辑的一部分,因此异常由被调用函数的异常处理机制处理。
- return语句的控制权转移:return语句的执行分为两步:首先完成返回值的初始化(包括拷贝/移动操作),只有当这一步成功完成后,才会执行函数的退出逻辑(销毁局部变量、转移控制权到调用点)。如果初始化过程抛出异常,return语句的执行被中断,函数并未退出,控制权仍在f内部,因此异常会被f内的catch块捕获。
测试代码
#include<iostream> struct S{ S(const S &){ throw "Oops"; } S(int) noexcept {} }; S f(){ static/*to avoid RVO*/ S stat(7); try{ return stat; }catch(const char *what){ std::cerr << "still in function after failed-return" << std::endl; } return S(7);// mandatory copy-elision (c++17); } int main() try{ auto s = f();// mandatory copy-elision (c++17); }catch(...) { std::cerr << "Exception from main..." << std::endl; }
内容的提问来源于stack exchange,提问作者Adrian
相关产品推荐
相关产品推荐

