你如何记住rvalue、lvalue等之间的区别?

10

这个问题很好,因为它有关于rvalue, lvalue, xvalue, glvalue, 和 prvalue 的区别的答案。排名第一的答案对每一个都有很好的解释,我在阅读时理解了它们的区别。然而,我很难记住它们的区别,并且每次有人使用这些术语时,我都需要通过谷歌来提醒自己哪个是哪个。

是否有任何常见的提示或其他方式让人记住哪个是哪个? 我真的想能够在我的脑海中清晰记住它们,而不像我目前那样混淆它们。


从您的链接问题中,我认为一行答案“C++03 lvalue仍然是C++0x lvalue,而C++03 rvalue在C++0x中称为prvalue。”是最容易理解的方式。 - Jesse Good
1
@关闭投票者:哪里是更合适的地方来询问这个问题? - Cornstalks
1
@Cornstalks:programmers.se是什么? - Mac
3个回答

9

我做了两个关联:

  • 只能获取lvalue的地址
  • xvalues是std::move表达式的内容

如果不是这两种情况,则可能是prvalue。

现在,为了记住glvalues和rvalues,我简单地想象了这个图:

lvalues和xvalues都是glvalues,而xvalues和prvalues都是rvalues。这实际上是你需要知道的全部内容。

也许一个助记符可以帮助记住lvaluse、xvalues和prvalues,放在底部的单词是Lower eXPRessions(它包含L、X和PR)。也可能不需要。


3
你通常只需要知道一个表达式是左值还是右值。这两种表达式的类别是互相独立的。
通常情况下,左值表达式指的是会持续存在一段时间的东西。例如,变量名是一个左值,因为变量会一直存在。另一方面,右值表达式通常指的是临时存在的东西。你只能取一个左值的地址,因为你为什么需要临时消失的东西的地址呢?
现在,在做出这个区分时,你必须考虑到编译器在这个时刻所知道的内容。例如,考虑函数 void foo(const A& a)。在这个函数内部,编译器不知道传递的对象是一个临时对象还是其他类型的对象,所以它只是假设它将继续存在。也就是说,a 是一个左值。即使你可以轻松地将一个临时对象传递到这个函数中(使用一个右值表达式进行调用),表达式 a 仍然是一个左值。
考虑到这一点,你可以通过是否命名来进一步记住一个东西是左值还是右值。在上面的例子中,因为对象被命名为 a,所以它是一个左值。
现在,对于其余的类别,你应该记住以下图表:
注意,左值和右值确实是不同的。但是,右值被分为另外两个类别,xvalues 和 prvalues。此外,xvalues 也被视为 glvalues,以及所有左值表达式。
现在知道它们何时出现就归结于记住一些情况。
xvalues 并不常见。它们只出现在涉及到转换为右值引用的情况下。以下是所有情况:
- 返回右值引用的函数的结果 - 转换为右值引用的类型 - 如果对象是 xvalue,则为 object.x - 如果 pobject 是 xvalue,则为 object.*member 按定义,prvalues 是除 xvalue 之外的任何其他类型的 rvalue。例如,从函数按值返回一个对象会创建一个临时返回对象。表示该对象的表达式是一个 prvalue。
类别 glvalue 用于指代除 prvalue 之外的所有东西。

0

在编程中,lvalue 可以被视为“命名”的变量或内存位置... rvalue 可以被视为“未命名”的内存位置(即从函数返回的临时变量)或纯“值”(例如数字)。


只是好奇,你能举个快速的例子吗?我相信所有的lvalue都必须有一些类型的“内存位置”,可以通过名称访问。 - Jason
1
假设有 std::map<std::string, int> m;,那么 m["test"] 的名称是什么? - Ben Voigt
好的,我明白你的意思,但是我认为你是通过“名称”再次访问该内存位置,在这种情况下,你是通过m上的operator[]进行索引。例如,int foo() { return 5; }的返回值的“名称”是什么?那就是“未命名”的例子。但在你的情况下,你是通过一个命名的对象实例来访问内存位置,因此它是一个左值。 - Jason
那么对于 std::vector<double> v(10);v.begin() 没有名称,但是 *v.begin() 有名称吗? - Ben Voigt
好的,你抓住我了 :-) ... 是的,我将它们分成这两类有点过于简单化了,对于迭代器操作的细微差别来说是如此。当然,v.begin()并没有真正地从向量中返回一个对象,而是返回一个“指针”(即迭代器)。另一方面,*v.begin()实际上确实返回向量中的对象。所以我想这就是一个例子,你可以说一个rvalue在使用我的简单规则时有一个“名称”,打破了这个系统,但值得一提的是,在大多数情况下,这个思想的简单性都是适用的。 - Jason
显示剩余3条评论

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