左值引用的左值引用是否合法?
考虑以下示例,最终rvalueRef中的两个案例在它所引用的内容或类型(或其他内容)方面是否存在差异?
Type& ref = GetReference()
Type&& rvalueRef = std::move(ref)
vs
Type value = GetValue()
Type&& rvalueRef = std::move(value)
答案 0 :(得分:3)
这两个代码都是正确的,并且在C ++中是100%合法的。仅在第一种情况下移动引用(或更好地说,如果使用适当的目标,则能够移动)的意义上存在差异,在第二种情况下,它是副本(请参阅下面的示例,澄清这个)。
请注意std::move
实际上并不移动对象。它只将对象转换为右值引用类型。就是这样。
另请注意,在两个情况下,rvalueRef
仍然是左值 - 具有名称(即要引用的标识符)的对象永远不会一个右值。因此,如果您实际上没有使用std::move
(或使用显式强制转换)再次移动它,那么根本没有任何区别。
这是一个具体的例子:
//given function
std::string& GetReference();
std::string GetValue();
//target function
void f(std::string param);
您的代码如下:
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-constructor或move-assignment!在你的情况下,没有任何一个调用。
答案 1 :(得分: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()
返回的对象的副本。 {1}}。