尽管现有答案提供了一种解决方法 usingstd::move
使您的程序可以编译,但必须说您的使用emplace_back
似乎是基于误解。
您描述它的方式(“我试图 [...] 使用emplace_back()
”将内容从一个向量移动到另一个向量)以及您使用它的方式表明您将其emplace_back
视为一种将元素移动到向量中的方法,并且ofpush_back
作为将元素复制到向量中的方法。您用来填充向量的第一个实例的代码似乎也暗示了这一点:
std::vector<obj> v;
for( int i = 0; i < 1000; ++i )
{
v.emplace_back(obj("Jon"));
}
但这不是emplace_back
和之间的区别push_back
。
首先,push_back
如果仅给定一个右值并且元素类型具有移动赋值运算符,even会将元素移动(而不是复制)到向量中。
其次,真正的用例是在原地emplace_back
构造元素,即当你想将对象放入一个尚不存在的向量时使用它。的参数emplace_back
是对象构造函数的参数。所以你上面的循环应该看起来像这样:
std::vector<obj> v;
for( int i = 0; i < 1000; ++i )
{
v.emplace_back("Jon"); // <-- just pass the string "Jon" , not obj("Jon")
}
您现有代码有效的原因是它obj("Jon")
也是构造函数(特别是移动构造函数)的有效参数。但是 的主要思想emplace_back
是您无需创建对象然后obj("Jon")
将其移入。当您传递而不是传递给它时,您不会从该想法中受益"Jon"
。
另一方面,在您的第二个循环中,您正在处理之前创建的对象。emplace_back
用它来移动已经存在的对象是没有意义的。同样,emplace_back
应用于现有对象并不意味着该对象被移动。它只意味着它是使用普通的复制构造函数(如果存在的话)就地创建的。如果你想移动它,只需使用push_back
, 应用于结果std::move
:
std::vector<obj> p;
for( int i = 0; i < 1000; ++i )
{
p.push_back(std::move(v[i])); // <-- Use push_back to move existing elements
}
进一步说明
1) 您可以使用 C++11 基于范围的 for 来简化上述循环:
std::vector<obj> p;
for (auto &&obj : v)
p.push_back(std::move(obj));
2)无论你使用普通的for循环还是基于范围的for,你都一个一个地移动元素,这意味着源向量v
将保持为1000个空对象的向量。如果您确实想在过程中清除向量(但仍然使用移动语义将元素传输到新向量),您可以使用向量本身的移动构造函数:
std::vector<obj> p(std::move(v));
这将第二个循环减少到只有一行,并确保源向量被清除。