在VC ++ 2019中,我无法emplace_back
和仅移动类型的{rvalue} list
。
#include <vector>
#include <list>
struct A
{
A(A&&) {}
};
using ListOfA = std::list<A>;
int main()
{
std::vector<ListOfA> v;
// Build error in VC++ 2019
// No error in Clang and GCC C++11 - C++2a
v.emplace_back(std::move(ListOfA()));
}
尝试在VC ++ 2019中进行构建会产生以下编译错误:
'A::A(const A &)': attempting to reference a deleted function
很显然,VC ++试图实例化A
的(左值)复制构造函数,(正确地)该构造函数不存在,因为我为A
明确定义了其中一个构造函数。
我认为通过从另一个list
移动实例化vector
到位的list
应该是有效的-也就是说,list
类确实可以拥有一个move constructor,我认为应该只是使新的list
拥有(移出的)list
中元素的所有权,而无需任何副本。
实际上,使用Wandbox,same code builds and runs without error使用GCC和Clang。
有人可以解释为什么此代码无法在VC ++ 2019中编译吗?我有一个误会吗-VC ++编译器在上面的代码中实例化(lvalue)复制构造函数,实际上是否有正当理由?
注意
当std::move(...)
不存在时,在VC ++中会发生相同的错误;即此行发生相同的错误:
v.emplace_back(ListOfA());
答案 0 :(得分:3)
MSVC使用std::list
的副本构造函数,因为它的move构造函数正在抛出。在重新分配期间,如果move构造函数抛出异常,则std::vector
无法提供标准所要求的强异常保证。
在您的情况下,向量在重新分配之前没有任何元素,因此似乎没有调用复制构造函数,但这并不意味着不需要复制构造函数。
libstdc ++和libc ++中的 std::list
具有noexcept
的move构造函数。这是允许的,但不是标准要求的。