不幸的是它在编译时有效。
虽然编译器使用 noexcept 来优化异常处理代码,使代码性能更高,但遗憾的是他们没有进一步推动它给 noexcept语义。
理想情况下,当您将方法标记为 noexcept 时,它应该也意味着该方法不应该让任何异常冒泡。因此,如果您有一个标记为 noexcept 的方法,但它调用了未标记为 noexcept 的其他方法,那应该会给您一个编译错误,除非有一个 try/catch 阻止任何可以抛出的东西。
简单地调用 std::terminate 是一个非常糟糕的语言设计选择,因为它不会让编写 noexcept 方法的人承担任何责任。相反,它甚至使消费者无法解决问题,从而损害了软件的重用。
例如,假设我是一个糟糕的库开发人员,我编写了以下代码:
我的库附带的头文件 Foo.h:
class Foo
{
public:
void DoSomething() noexcept;
};
您是 FooLib 编写 Bar 应用程序的快乐消费者:
Bar.cpp
#include "Foo.h"
int main()
{
Foo foo;
try
{
foo.DoSomething();
}
catch (...)
{
std::cout << "Yay!" << std::endl;
}
return 0;
}
该代码可以正常编译并正常运行,直到您有 Foo 抛出异常...如果您将 foo.DoSomething() 的调用用 括起来,则没有任何区别>try/catch 块。代码将简单地中止。
如果您没有 Foo 的代码,则无法修复它。在这种情况下,唯一的解决方案是丢弃 Foo 库并编写自己的库。
Foo.cpp 的内容可以是这样的:
static void PotentiallyThrowException()
{
throw 0;
}
void Foo::DoSomething() noexcept
{
PotentiallyThrowException();
}
请注意,由 Foo::DoSomething() 的实现者将自己的调用包装到 try/catch 中。但是由于同样的问题,如果他们正在调用标记为 noexcept 的其他方法并且那些开发人员没有这样做,那么现在是 Foo::DoSomething()那是软管。以此类推。
我们可以肯定地说,从语义的角度来看,noexcept 不仅无用,而且有害。