在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
字符串为空。
为什么第一个更现代的符号不起作用?
答案 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>
的原因。