2016-07-23 90 views
-1

写了下面的代码vs13:为什么的std ::动未动

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)); 

作品,但没有动,叫字符串拷贝构造函数来代替。 myvector最后还是有他的“Hello World”。 使用常规的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字符串是空的。 为什么第一个现代符号不起作用?

+4

第一个例子是否真的编译?我不认为'std :: move(* s)'中应该有'*'。 – aschepler

+0

请注意,没有人曾表示移动应该删除原始文件。移动后,原始文件处于*有效但未指定*状态。即使将'&&放在适当的位置,对原始对象具有与新对象相同的值(即,与之前相同,直到修改),这是完全有效的(并且,imho,有时是期望的)。 – lorro

回答

5

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

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

+2

..即使如此,你也不能保证旧的字符串清空。 – lorro

+0

事实上,这是使用'std :: move'的正确方法(在第二个例子中,它可能会在OP的编译器中清空) – Xiobiq

+0

正确的方法:我同意你的看法。除了清空:这是编译器的类*和*的实现细节(两者都不)。 – lorro

3

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

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

未公知的,但有一个专用的算法用于容器之间移动的物体。它实际上也被称为std::move

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

编辑:

问:由于性病::移动只是强制转换为右值引用是不是真的需要?不是std :: move在这种情况下只是多余的?不,因为变量(如val)不能是r值参考。这就是为什么我们需要在通用引用上调用std::forward<T>

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

+0

由于'std :: move'只是强制转换为右值引用,它真的需要吗?在这种情况下不是'std :: move'只是多余的? – Xiobiq

+1

3-param'move',很好的提示。 – lorro

+0

非常感谢,非常有帮助的解决方案 – orenshochat

相关问题