C ++编译器何时推断出方法的noexcept?

时间:2018-06-06 16:29:22

标签: c++ gcc compiler-optimization move-constructor noexcept

我注意到我的std::vector<Foo>正在复制而不是在调整大小时移动其元素 - 即使Foo有移动ctor:

class Foo {
    // ...
    Foo(Foo&& other) : id_(other.id_), ptr_(other.ptr_), flag(other.flag)
    {
        other.flag = false;
    };
    // ...
    int   id_; 
    void* ptr_; 
    bool  flag;
}

然后我读了:

Resize on std::vector does not call move constructor

这提醒我std::vector只会在元素'移动ctor被声明为noexcept时使用移动构造。当我添加noexcept时,会调用移动ctor。

我的问题是:为什么,考虑到移动ctor的代码,编译器是否确定它不是noexcept?我的意思是,它可以知道一个事实,即不能抛出异常。是否推断标准不允许noexcept,或者不仅仅是由我的特定编译器完成?

我在GNU / Linux上使用GCC 5.4.0。

1 个答案:

答案 0 :(得分:3)

tl; dr:不允许编译器推断noexcept

  

为什么,考虑到移动ctor的代码,编译器是否确定它不是noexcept?

因为noexcept规范是根据声明确定的 - 而不是定义。这类似于const规范的工作原理。即使编译器的实现没有修改任何成员,也不允许编译器将函数确定为const。

  

推断标准

不允许除外

据我了解,是的:

  

[except.spec] ... a中没有异常规范   除了析构函数(12.4)或解除分配函数(3.7.4.2)之外的函数声明符表示   异常规范,是所有类型的集合。

推断除了所有类型之外的其他内容会违反此规则。当然,当编译器可以证明不能抛出任何异常时,它可以在as-if规则下优化掉任何堆栈展开代码,但是这样的优化不会影响SFINAE内省。

discussion介绍noexcept(auto)的可能性,这将是一种显式方式,让编译器推断出noexcept规范。