为什么允许在noexcept-tagged函数中抛出异常?

tun*_*nuz 7 c++ tags compilation exception noexcept

我很难理解这一点.

double compute(double x, double y) noexcept
{
   if (y == 0)
       throw std::domain_error("y is zero");
   return x / y;
}
Run Code Online (Sandbox Code Playgroud)

这在clang中编译得很好(我没有检查过gcc),但这对我来说似乎是胡说八道.为什么编译器允许noexcept函数包含throw语句?

And*_* DM 10

一个声称不会抛出的函数实际上可能会抛出。
如果noexcept函数确实抛出,terminate则调用,从而强制承诺在运行时不抛出。

// The compiler does not check the `noexcept` specification at compile time.
void f() noexcept // Promises to not throw any exception
{
    throw runtime_error("error"); // Violates the exception specification
}
Run Code Online (Sandbox Code Playgroud)

指定函数不会抛出向非抛出函数的调用者承诺,他们将永远不需要处理异常。

要么函数不会抛出,要么整个程序将终止。


Bar*_*rry 7

会发生什么是std::terminate()触发,因为您的异常规范不允许这种情况发生(参见[except.spec/9]).

至于为什么允许这样做,根本无法彻底检查是否有违反规范的内容.考虑类似的事情:

double f(double );
double compute(double x, double y) noexcept
{
    return x / f(y);
} 
Run Code Online (Sandbox Code Playgroud)

可以f扔?不能说.

  • @Calmarius 定义类似。如果您调用非“noexcept”函数,您希望它“不编译”吗? (4认同)
  • 至少警告。在不允许抛出的函数中调用抛出函数是一个编程错误,应该在编译时捕获。 (3认同)
  • 在您的示例中,`f`没有使用`noexcept`规范声明,因此可能会抛出。编译器可以检测到。实际上,它与const正确性有相似之处。为什么也不能对noexcept做到这一点? (2认同)
  • @Calmarius 这真的不是编程错误。您可以确保潜在抛出函数不会以其他方式抛出。或者潜在抛出函数无论如何都不会抛出并且只是在 C++11 之前编写的。 (2认同)

归档时间:

查看次数:

2452 次

最近记录:

9 年,5 月 前