为什么std :: move没有移动

时间:2016-07-23 22:17:05

标签: c++ c++11 visual-studio-2013

在vs13中写了以下代码:

std::vector<std::string> myvector(1000);
std::fill(myvector.begin(), myvector.end(), "Hello World");
std::vector<std::string> pushto;
for (auto s: myvector)
    pushto.push_back(std::move(*s));

工作但没有移动,它改为称为字符串复制ctor。 myvector最后还有他的#34; Hello World&#34; s。 像这样使用常规的c ++ 98迭代:

 std::vector<std::string> myvector(1000);
 std::fill(myvector.begin(), myvector.end(), "Hello World");
 std::vector<std::string> pushto;
 for (auto s = myvector.begin(); s != myvector.end();s++)
    pushto.push_back(std::move(*s));

实际工作,并且调用了移动。 myvector字符串为空。 为什么第一个更现代的符号不起作用?

2 个答案:

答案 0 :(得分:5)

在您的第一个示例中,您使用的是for (auto s: myvector)s在这种情况下是当前迭代中值的副本。要完成你想要的,你应该通过参考 - for (auto& s: myvector)来完成。

请注意,std::move后不保证字符串被清空,此调用只是将其参数转换为右值引用(&&)。其他函数(例如std::vector::push_back)具有rvalue referece参数的重载可能释放他们的argumnet资源。

答案 1 :(得分:3)

正如@Polikdir所说,复制来自你在(auto s: myvector)制作的副本。一种方法是使用range-for循环,&&(转发引用)或&(正常引用):

for (auto & val : myvector)
    pushto.push_back(std::move(val));

不为人知,但有一种专用的算法可以在容器之间移动对象。它实际上也称为std::move

std::move(s.begin(), s.end(), std::back_inserter(pushto)); 

编辑

q:由于std :: move只是强制转换为右值引用,它真的需要吗?在这种情况下std :: move是不是冗余?不,因为变量(例如val)不能是r值引用。这就是我们需要在通用引用上调用std::forward<T>的原因。

另请注意:What does `auto && e` do in range-based for-loops?