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