2014-04-11 150 views

回答

3

这两个代码都是正确的,在C++中是100%合法的。只有在第一种情况下引用被移动(或者更好地说,在使用适当的目的地时能够移动)并且在第二种情况下,它是副本(参见下面的示例以便解释这个)

请注意,std::move实际上并没有移动对象。它仅将该对象转换为右值引用类型。就是这样。

还要注意,在这两种案件,rvalueRef仍然左值—一个对象,它有一个名字(即一个标识符来指代)是从来没有一个rvalue。所以,如果你实际上没有使用std::move(或使用显式投射)实际移动它,那么根本没有任何区别。

这里是一个具体的例子:

​​

您的代码如下:

std::string& ref = GetReference(); 
std::string&& rvalueRef = std::move(ref); 

std::string value = GetValue() 
std::string&& rvalueCopy = std::move(value); //named changed 

至今并无影响。

但是,如果你这样做:

f(std::move(rvalueRef)); //actual object returned from GetReference is moved! 
f(std::move(rvalueCopy)); //only a copy is moved. 

实际对象移动在第一种情况下,和在第二种情况下,复制移动。

f(std::move(GetReference())); //actual object returned from GetReference is moved! 
f(std::move(GetValue()));  //only a copy is moved. 

所以你看,在你的代码,没有任何区别,因为在所有没有实际MOVE:如果这样做,这是没有任何差别。只有演员在那里。为了实际移动,应该有一个适当的目标类型,可以调用移动构造函数或移动赋值!在你的情况下,没有任何一个的调用。

1

问:有一个右值引用右值引用是合法吗?

这不是你问的问题。您真正要问的问题是这样的:

问:将左值引用转换为右值引用是合法吗?

答案是肯定的。 std::move只是将它的参数转换为一个右值引用,这总是合法的。你在做什么的整体正确性取决于你如何处理结果std::move。您的示例代码没有任何问题。

问:这两种情况有区别吗?

// case 1        // case 2 
Type& ref = GetReference();   Type value = GetValue(); 
f(std::move(ref));     f(std::move(value)); 

唯一的区别是,在情况1中,ref是由GetReference()返回的对象的引用,但在情况2中,value是由GetValue()返回的对象的副本。