我发布了这个答案:https://stackoverflow.com/a/28459180/2642059其中包含以下代码:
void foo(string&& bar){
string* temp = &bar;
cout << *temp << " @:" << temp << endl;
}
bar
是左值还是右值?
我问,因为我显然不能取rvalue的地址,但我可以像这里所做的那样获取右值引用的地址。
如果你可以对左值参考执行任何操作,你可以在左值参考上用&#34;&amp;&amp;&#34;来区分两者。而不仅仅是&#34;&amp;&#34;?
答案 0 :(得分:36)
bar
是左值还是右值?
问题回答了自己。任何名称都是左值(1)。所以bar
是一个左值。它的类型是&#34;对string
&#34;的右值引用,但它是该类型的左值。
如果您想将其视为左值,则需要对其应用std::move()
。
如果你可以对左值参考执行任何操作,你可以在左值参考上用&#34;&amp;&amp;&#34;来区分两者。而不仅仅是&#34;&amp;&#34;?
这取决于您对&#34;执行操作的定义。&#34;左值引用和(命名)右值引用在表达式中如何使用它们几乎完全相同,但它们在可以绑定到它们的内容上有很多很多。左值可以绑定到左值引用,右值可以绑定到右值引用(任何东西都可以绑定到const
的左值引用)。也就是说,您不能将右值绑定到左值引用,反之亦然。
让我们来谈谈右值参考类型的函数参数(例如你的bar
)。重要的不是bar
是什么,而是您对bar
所指的价值的了解。由于bar
是一个右值引用,因此您肯定知道绑定到它的任何内容是一个右值。这意味着当完整表达式结束时它必然会被销毁,而你可以安全地将其视为右值(通过窃取其资源等)。
如果您不是直接向bar
执行此操作的人,但只是想通过bar
,则您有两种选择:要么完成{{1}然后你应该告诉下一个接收它的人,它被绑定到右值 - bar
。或者您需要使用std::move(bar)
执行更多操作,因此您不希望任何人在中间窃取其资源,因此请将其视为左值 - bar
。
总结一下:不同之处在于,只要你拥有它就可以使用引用。区别在于可以绑定到引用强>
(1)一个好的经验法则,除了少数例外:枚举器有名称,但是rvalues。类,名称空间和类模板都有名称,但不是值。
答案 1 :(得分:8)
bar是 rvalue 还是左值?
它是左值,就像命名变量的任何表达式一样。
如果您可以对右值参考执行任何操作,您可以在左值参考上使用&#34;&amp;来区分两者之间的区别;&安培;&#34;而不仅仅是&#34;&amp;&#34;?
您只能使用 rvalue 表达式初始化 rvalue 引用。因此,您可以将临时字符串传递给您的函数,但是您无法在不明确移动字符串变量的情况下传递字符串变量。这意味着你的函数可以假设不再需要参数,并且可以从中移动。
std::string variable;
foo(variable); // ERROR, can't pass an lvalue
foo(std::move(variable)); // OK, can explicitly move
foo("Hello"); // OK, can move from a temporary
答案 2 :(得分:0)
在这种情况下, 名为rvalue引用是lvalues ,而如果输入类型是 const名为rvalue references 那么它将是 rvalue ,这是一个简单的例子:
#include <string>
#include <iostream>
void foo(const std::string&& bar) {
std::string* temp = &bar; // compile error, can't get address
std::cout << *temp << " @:" << temp << std::endl;
}
int main()
{
foo("test");
return 0;
}
希望这很有用。
答案 3 :(得分:0)
表达式bar
是一个左值。但这不是“对字符串的右值引用”。表达式bar
是左值引用。您可以通过在foo()中添加以下行来验证它:
cout << is_lvalue_reference<decltype((bar))>::value << endl; // prints "1"
但是我同意对Angew的其余解释。
右值引用绑定到右值后,就是左值引用。实际上,不仅仅针对函数参数:
string&& a = "some string";
string&& b = a; // ERROR: it does not compile because a is not an rvalue
如果您可以在右值引用上执行任何操作,而可以在左值引用上执行任何操作,那么用“ &&”(而不仅仅是“&”)区分两者的意义何在?
右值引用允许我们在右值到期之前执行一些“左值操作”。