为什么 std::move 没有移动

Why std::move didn't move

本文关键字:移动 move std 为什么      更新时间:2023-10-16

在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在最后仍然有他的"你好世界"。使用像这样的常规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字符串为空。为什么第一个更现代的符号不起作用?

在您使用for (auto s: myvector)的第一个示例中,s在本例中是当前迭代中值的副本。要完成您想要的,您应该通过引用for (auto& s: myvector)来完成。

请注意,不能保证在std::move之后清空字符串,此调用只是将其参数强制转换为右值引用(&&)。其他函数(如std::vector::push_back)的右值引用参数重载可能会释放其argument资源。

正如@Polikdir所说,拷贝来自您在(auto s: myvector)中制作的拷贝。一种方法是使用循环的范围,使用&&(转发参考)或&(正常参考):

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>

另请注意:什么是`auto&amp;e`do基于范围的循环?