C++不可拷贝类能否按值捕获异常?Clang与GCC谁的实现正确
结论
Clang 的行为符合 C++ 标准的规定,GCC 可以编译通过属于不符合标准的实现偏差。
规则说明
对应代码场景:
struct B { B() = default; B(const B&) = delete; }; int main() { try { throw B{}; } catch( B ) { } }
拆分两个核心执行环节的标准要求判断:
- throw 环节:C++17 引入了强制复制消除规则,
throw B{};中的纯右值B{}会直接在异常存储区构造异常对象,不需要调用拷贝/移动构造,这一步两个编译器的处理均符合标准。 - catch 按值捕获环节:C++ 标准明确要求,按值捕获的 catch 参数需要从异常对象执行拷贝初始化。而异常对象属于左值,必须调用类型的拷贝构造函数完成参数的构造。
结构体 B 显式删除了拷贝构造函数,同时由于用户自定义了拷贝构造函数,C++ 标准不会为 B 隐式生成移动构造函数,没有可用的构造函数能完成 catch 参数的初始化,因此程序本身是不合法的,编译器必须输出错误。
GCC 可以编译通过属于对应版本的实现 Bug 或非标准扩展,并不符合 C++ 标准的强制要求。
内容的提问来源于stack exchange,提问作者Fedor
相关产品推荐
相关产品推荐

