我注意到我的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。
答案 0 :(得分:3)
noexcept
为什么,考虑到移动ctor的代码,编译器是否确定它不是noexcept?
因为noexcept规范是根据声明确定的 - 而不是定义。这类似于const规范的工作原理。即使编译器的实现没有修改任何成员,也不允许编译器将函数确定为const。
推断标准
不允许除外
据我了解,是的:
[except.spec] ... a中没有异常规范 除了析构函数(12.4)或解除分配函数(3.7.4.2)之外的函数声明符表示 异常规范,是所有类型的集合。
推断除了所有类型之外的其他内容会违反此规则。当然,当编译器可以证明不能抛出任何异常时,它可以在as-if规则下优化掉任何堆栈展开代码,但是这样的优化不会影响SFINAE内省。
有discussion介绍noexcept(auto)
的可能性,这将是一种显式方式,让编译器推断出noexcept规范。