假设C ++编译器正在编译一个函数,该函数的定义在与其调用相同的转换单元中可用。假设它不会抛出自身,也不会调用已知的抛出函数。假设也没有调用extern C
代码,也不会调用具有潜在零值的数字除法。
在这些假设下,编译器会将函数视为noexcept
吗?如果没有,是否有推断noexcept
的其他条件?
具体来说,如
这样的超简单功能呢?void foo() { } /* this one */
class A {
int x_;
public:
x() const { return x_; } /* ... and this one */
}
我想要的答案仅基于标准,最重要的,也可能是GCC和clang所做的。
答案 0 :(得分:5)
除非您明确使用noexcept
说明符,否则几乎所有函数都可能被抛出。例外情况是您自己对delete
(释放函数)的定义,以及一些特殊的成员函数:构造函数,析构函数和赋值运算符。 (C ++ 17)
来自[except.spec]
如果函数的声明没有 noexcept-specifier ,则声明可能会抛出 异常规范,除非它是析构函数或释放函数或在其第一个声明中是默认的, 在这种情况下,异常规范如下所述,该函数的其他声明均不应如此 有一个 noexcept-specifier 。
隐式noexcept
除非为任何成员(或成员的成员等)执行任何初始化,否则可能会抛出
隐式noexcept
除非潜在构造的子对象的任何析构函数可能抛出。
隐式noexcept
,除非任何使用内部分配都可能被抛出。
以下是一些演示上述内容的示例代码(clang 6.0.0,gcc 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()));
}
使用=default
或允许编译器通过省略生成自己特殊成员函数版本的另一个原因。