【发布时间】:2016-02-10 14:56:31
【问题描述】:
似乎在至少某些编译器(GCC 5.2 和 Visual C++ 2015 Update 1)的现代版本中,当存在已初始化的类成员时,会错误地生成 noexcept 默认构造函数:
#include <memory>
#include <exception>
#include <iostream>
struct E {};
struct A
{
A()
{
throw E();
}
};
struct B
{
A a;
};
struct C
{
std::shared_ptr<B> b{ std::make_shared<B>() };
//C() {} // uncomment to fix
};
int main()
{
try
{
new C;
}
catch (const E &)
{
std::cout << "Exception caught\n";
}
std::cout << "Exiting...\n";
}
运行此代码会导致在 GCC 5.2(C++14 模式)和 Visual C++ 2015 Update 1 上调用(而不是调用 catch 块)std::terminate。
现场示例: http://coliru.stacked-crooked.com/view?id=16efc34ec173aca7
取消注释空构造函数可修复 Visual C++ 的此代码,但不能修复 GCC。无论如何,Clang 3.6 正确(我想?)调用 catch 块。
标准中是否有任何规则规定默认生成的构造函数何时必须标记为noexcept?
【问题讨论】:
-
如果您明确告诉生成默认构造函数 (
C() = default;) 会发生什么? -
是的,有规则。从[except.spec]/17开始往上走。
-
只是说
=default不会改变任何事情。我试过指定C() noexcept(false)=default;但这会产生语法错误 -
@T.C.它仅指特殊的成员函数,没有提及成员变量的构造函数。
-
或许值得记住的是,规则在 C++14 之后发生了变化。 T.C. 链接的规则可能是也可能不是您的特定版本的编译器实现的。
标签: c++