为何C++中默认生成的noexcept构造函数报错,手动实现则正常?
为什么默认生成的noexcept构造函数报错,手动实现的却不会?
问题描述
为什么用= default标记的noexcept构造函数会报错,手动实现的却不会?我本来以为这两种写法效果差不多,求解答。
代码示例
class B { public: B() { throw int(42); } }; class A { public: A() noexcept = default; // error: use of deleted function ‘A::A()’ // note: ‘A::A() noexcept’ is implicitly deleted because // its exception-specification does not match the implicit exception-specification ‘’ //A() noexcept : m_b{}{} B m_b; };
错误提示
错误:使用已删除的函数‘A::A()’
注释:‘A::A() noexcept’被隐式删除,因其异常规范与隐式异常规范不匹配。
原因解释
核心差异在于编译器对默认生成构造函数和手动实现构造函数的异常规范处理逻辑完全不同:
= default构造函数的规则:
编译器会根据类的成员变量、基类的构造函数自动推导默认构造函数的异常规范。因为A的成员m_b是B类型,而B的默认构造函数会抛出异常,所以编译器推导出来的A的默认构造函数异常规范是允许抛出异常的。
当你手动给= default的构造函数加上noexcept时,就和编译器推导的结果冲突了,这时编译器会直接隐式删除这个构造函数,导致编译报错。手动实现构造函数的规则:
手动写的构造函数,异常规范是你自己指定的,编译器不会去验证这个规范是否和成员构造函数的实际行为兼容。哪怕m_b的构造函数会抛出异常,只要你写了noexcept,编译阶段就会通过——但运行时如果真的抛出异常,程序会直接调用std::terminate终止。
简单来说:= default的构造函数是让编译器按规则生成,你加的noexcept如果不符合规则就会被删;手动写的构造函数是你说了算,编译器只认你写的异常规范,不管实际会不会抛。
内容的提问来源于stack exchange,提问作者chuong vo
相关产品推荐
相关产品推荐

