“lvalue”和“rvalue”的命名背后的推理是什么?

7
在C/C ++中,“lvalue”和“rvalue”的命名背后的原因是什么?

1
既然你知道它们是什么,那你为什么还要问呢? - Kiril Kirov
3
太荒谬了,这个问题被踩得那么多。这是一个非常清晰和有效的问题,在网页文章中并不总是解释得很清楚,而且答案对于记住每种值类型都是什么有帮助。非常值得。 - Syndog
1
@curiousguy - 更有理由去问。唯一问题在于当没有好的答案时,问为什么才会成为问题。 - Syndog
@Syndog 不是我的话,也不是我的规则。我告诉你这个是因为其他人会因为那个而给你点踩。 - curiousguy
1
@curiousguy - 我相信那是真的,但这并不能使一个本来有效和有帮助的问题成为“有问题的”。 - Syndog
显示剩余4条评论
6个回答

17

标准提到了这个:

一个左值(历史上称为左值,因为左值可以出现在赋值表达式的左侧)[...]

一个右值(历史上称为右值,因为右值可以出现在赋值表达式的右侧)[...]

也就是说,一个左值是你可以赋值的东西,而一个右值是你可以从中赋值的东西。

然而,这与事实逐渐越来越远。一个无法分配的左值的简单例子是一个const变量。

const int x = 5;
x = 6; // Error

当涉及操作符重载时,您甚至可以在赋值的左侧出现右值。

我认为将lvalue视为引用存储在内存中的对象,将rvalue视为仅仅是一个值(可能已经从内存中读取)。这些概念很好地反映了这个想法。以下是一些示例:

  • 可以将Lvalue-to-rvalue视为从内存中读取一个值。
  • 大多数运算符需要进行lvalue-to-rvalue转换,因为它们使用对象的值来计算结果。
  • 地址运算符(&)需要一个lvalue,因为你只能获取内存中的某个东西的地址。它不需要获取对象的值来计算其地址。
  • 执行std::move将lvalue表达式转换为rvalue表达式可以被看作是欺骗编译器,使其认为存储在内存中的对象实际上只是临时值。

然而,在每种情况下都不能保持这样的说法。这只是个合理的类比。


你也不能获取位域的地址。 - curiousguy
"&" 运算符需要一个左值,因为它就是这样规定的,没有什么可说的。 - curiousguy
进一步阅读:https://en.cppreference.com/w/cpp/language/value_category - arseniiv

4

早期,“lvalue”指的是可以放在赋值语句左侧的内容,而“rvalue”则指可以放在赋值语句右侧的内容。


3

如果你考虑到赋值运算符的哪一侧可以出现它们,那么这是相当直观的:

left-value = right-value;

简单来说,lvalue 表示可以对其进行赋值,而 rvalue 只能出现在操作符的右侧。


3
随着时间的推移,其含义已经发生了变化。对于用户定义的赋值运算符,您可以在左边使用rvalue,或要求右边使用lvalue,但是从历史上看,这就是原因。 - David Rodríguez - dribeas

1
在C语言中,lvaluervalue反映了赋值运算符的用法。 rvalue只能出现在=的右边,而lvalue可以出现在任一侧。在C++中,情况类似,但更加复杂。
存在不可赋值的lvalues,即常量变量。

2
数组是不可分配的lvalue的另一个例子。 - Daniel Fischer

0

'l'在lvalue中的起源是来自于“left” value(即赋值运算符左侧); 然而,现在它代表位置值,并且指任何占据某个可识别内存位置的对象(即具有地址)。rvalue现在是指任何不是lvalue的东西。


0

这是对一个(稍微复杂一些的)概念简化后的结果。

lvalue 是左值,即“可以出现在赋值语句的左侧”的值。这是一个简化,不是所有的左值都可以直接按原样分配(例如,数组不能,只有非 const 数组的元素可以,因此需要使用下标)。

rvalue 是右值,即只能出现在赋值表达式的右侧的值。


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