在什么情况下C++编译器推断noexcept?

ein*_*ica 11 c++ exception compiler-optimization noexcept

假设C++编译器正在编译一个函数,该函数的定义在与其调用相同的转换单元中可用.假设它不会抛出自身,也不会调用已知的抛出函数.假设也没有extern C调用代码,也没有调用潜在零值的数字除法.

在这些假设下,编译器会将函数视为noexcept?如果没有,是否有noexcept推断的附加条件?

具体来说,超简单功能如何

void foo() { } /* this one */
class A { 
    int x_; 
public: 
    x() const { return x_; }  /* ... and this one */
}
Run Code Online (Sandbox Code Playgroud)

我想要的答案仅基于标准,最重要的,也可能是GCC和clang所做的.

And*_*dyG 5

除非您明确使用noexcept说明符,否则假定几乎所有函数都可能抛出。例外是针对您自己的delete(重新分配函数)定义和一些特殊的成员函数:构造函数,析构函数和赋值运算符。(C ++ 17)

来自[except.spec]

如果函数的声明没有noexcept-specifier,则该声明具有可能抛出的异常说明,除非它是析构函数或释放函数或在其第一个声明中默认为默认值,在这种情况下,异常说明如下所述该函数的其他任何声明都不应具有noexcept-specifier

建设者

是隐式的,noexcept除非对任何成员(或成员的成员等)执行的任何初始化都可能引发

破坏者

是隐式的,noexcept除非潜在构造的子对象的任何析构函数都可能引发。

赋值运算符

是隐式的,noexcept除非内部可能有任何使用分配的情况。


这是一些示例代码,演示了以上内容(clang 6.0.0gcc 8.0.0):

int foo() { return 1; }
int bar() noexcept{ return 1; }

struct Foo{};

struct Bar{
 Bar(){}
};

int main()
{
    static_assert(noexcept(bar()));
    static_assert(!noexcept(foo()));
    static_assert(noexcept(Foo()));
    static_assert(noexcept(Foo().~Foo()));
    static_assert(noexcept(Foo().operator=(Foo())));
    static_assert(!noexcept(Bar()));
    Bar b;
    static_assert(noexcept(b.~Bar()));
}
Run Code Online (Sandbox Code Playgroud)

使用=default或允许编译器通过省略来生成自己的特殊成员函数版本的另一个原因。