从技术上讲,noexcept指定移动c是要求向量使用移动而不是复制c' tor。
我发现GCC 7并非如此。
std::vector<A> v;
v.push_back(A("555")); //triggers move c'tor
上述工作只要A实现移动c并指定移动c,因为不需要noexcept。
我想知道这是GCC问题还是编译器正常? 或者我是否误解了某些事情?
答案 0 :(得分:1)
该标准不需要noexcept
T
移动构造函数,以便在调用std::vector<T>::push_back(T&&)
以下是关于push_back(T&& rv)
标准的说法(参见[sequence.reqmts]):
附加
rv
的副本。
需要:T应该是MoveInsertable
进入[vector
]。
MoveInsertible
是一个奇特的概念,只是意味着可以使用右值引用*来构造您的类型。例如。通过移动构造函数,但通过复制构造并不是不可能的。
我认为你将这一点与以下事实相混淆:根据移动构造函数是否被声明noexcept
,std::vector
可以做出不同的异常保证。请参阅右值参考push_back
([vector.modifiers])的“备注”:
备注:...如果抛出其他异常 而不是由复制构造函数,移动构造函数,赋值运算符或移动赋值运算符
T
或任何InputIterator
操作都没有效果。如果在插入时抛出异常 最后的单个元素T
是CopyInsertable
或is_nothrow_move_constructible<T>::value
是true
,没有效果。否则,如果a的移动构造函数抛出异常 非 -CopyInsertable T
,效果未指定。
*更具体地说,您的类型MoveInsertible
是vector
还是分配器依赖。也就是说,对于A
的分配器vector
,以下内容必须完整:
allocator_traits<A>::construct(m, p, rv)
m
是您的分配器A
p
是指向您的类型的指针(T*
)(更确切地说,它是对齐存储,可以容纳T
)rv
是我们试图插入的左值(T&&
)