什么是lvalue?

25
可能重复:
什么是rvalues,lvalues,xvalues,glvalues和prvalues? C++标准主要在第5章“表达式”中定义了哪些表达式是lvalues,哪些是rvalues。我已经阅读了这一章,并且我相信我可以正确区分lvalues和rvalues。
然而,在我读好的C++书籍和/或标准之前,我曾经认为lvalue是指可以出现在赋值语句左侧的东西,而rvalue是指不能出现在赋值语句左侧的东西。显然,这个天真的定义有很多反例。后来,我又认为lvalue是指具有地址的东西,而rvalue是指没有地址的东西。这也有反例,比如一些临时对象,显然它们是有地址的。
一个朋友问我什么是lvalue和rvalue。我大致告诉了他是什么,但他要求一个更完整的答案。我告诉他去读标准,他拒绝费脑筋,说他肯定有一些“必要且充分的条件”来说明什么是lvalue。
例如,一个lvalue是非const引用可以绑定到的东西。但这个解释并不令人满意。我正在寻找更明显的东西,更容易解释的东西,而不是考虑每个表达式类型...
希望问题已经清楚了。

我认为你试图过于追求每个变量都有独特的定义。有些元素既可以是左值也可以是右值。例如:int a; int b; b = 4; a = b; - dee-see
之前有一个类似的问题,基本上是关于返回结构体的函数也可以被赋值的。所以你可以像这样做:foo() = whatever。这是问题的链接:https://dev59.com/Im025IYBdhLWcg3wRDu8(从下面的低评分答案中移动) - Mike Bailey
1
我很失望这个问题被认为是与任何建议的链接重复了。 - Armen Tsirunyan
5
我认为这句话已经是相当简单易懂的了,大概意思是:“lvalues 代表在一个表达式之后仍然存在的对象名称... rvalues 是指在它们所在的完整表达式结束时消失的临时对象”。此处引用自该网页:http://blogs.msdn.com/b/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx。 - James McNellis
@James:我实际上很喜欢这个定义。 - Armen Tsirunyan
显示剩余4条评论
4个回答

16

简单来说,rvalue是指表达式结果不会在该表达式结束后继续存在,而lvalue则会。这个基本原则使移动语义和rvalue引用成为可能-你可以修改它们而不会出现问题,因为你知道该对象的生命周期已经结束。


这并不是真的 - 你可以有一个指定临时对象的左值,以及指定静态存储期对象的右值(还有其他可能性)。 - M.M
@M.M,你能否提供这两种情况的例子? - user51462
对于第一个问题,可以在一个临时对象上调用的成员函数中使用*this。对于第二个问题,如果x是一个静态对象,则可以使用std::move(x) - M.M

12

我发现将lvalue视为“具有名称的事物”是最有用的简化方法。表达式++x是一个lvalue,其名称为x。相比之下,rvalue是“没有名称的事物”。x++是一个rvalue,因为它产生了一些无名的值。


+1 如果您真正阅读并理解了我的问题。但是 int& f() {int* p = new int; return *p;} f() 的名称是什么? :) - Armen Tsirunyan
1
@Armen:0x830D2CFF,或者任何new int产生的地址。我从来没有说过你需要访问名称:-P - Dennis Zickefoose
@Dennis:在这种情况下,我们不能把临时对象看作是有名称的对象吗(因为它有一个地址)? - Armen Tsirunyan
1
rvalues可以有名称(许多rvalues都有名称),而lvalues可能会缺少名称(许多lvalues确实缺少名称)。 - Johannes Schaub - litb
2
@Dennis,f()是一个rvalue,但不是一个临时对象。实际上,可以认为每个临时对象都有一个地址。每个临时对象都是一个对象,而对象是存储区域。但是,在C++中没有具有名称的临时对象(但并非每个无名对象都是临时对象!)。 - Johannes Schaub - litb
显示剩余3条评论

0

左值是指引用内存位置的东西。这是我能说的最简单的事情。右值可以是左值,右值只是表达式或常量的结果。


5
“An r-value can be an l-value” 不正确;在C++98中,一个表达式要么是rvalue要么是lvalue;lvalue可以隐式转换为rvalue。 - James McNellis

0

也许你只是对可修改的左值和非左值有点困惑。右值可以是左值或非左值。在 const 修饰符引入后,术语“可修改的左值”被使用(参见维基百科关于值的条目)。在 C++ 中,每个表达式都返回一个左值、右值或无值。当左值出现为右值时,它会被隐式转换为右值(参见IBM关于值类型的文章)。


1
不,我不认为我对这些概念感到困惑。 - Armen Tsirunyan
const限定符不是必需的来证明一个不可修改的左值:int x[3];在这里,x是一个不可修改的左值。 "rvalues can be lvalues or non-lvalues" 这是不正确的:没有rvalue是左值。每个表达式都是要么是左值要么是右值。有一个隐式转换允许将左值转换为右值。 - James McNellis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接