【问题标题】:How do you remember the differences between rvalue, lvalue, etc?您如何记住右值、左值等之间的区别?
【发布时间】:2012-12-18 18:36:29
【问题描述】:

This question 很棒,因为它回答了rvaluelvaluexvalueglvalueprvalue 之间的区别。最佳答案对每个都有一个不错的解释,当我阅读它们时,我理解它们的区别。但是,我很难将它们牢牢记在脑海中,每次有人使用这些术语来提醒自己哪个是哪个时,我都必须在 Google 上搜索它们。

是否有任何常见的助记符或其他方式让人们记住哪个是哪个?我真的很希望能够将它们全部记在脑海中,而不会像现在这样混淆它们。

【问题讨论】:

  • 从您的链接问题中,我认为单行答案A C++03 lvalue is still a C++0x lvalue, whereas a C++03 rvalue is called a prvalue in C++0x. 是最简单的思考方式。
  • @Close voters:问这个问题在哪里更合适?
  • @Cornstalks: programmers.se?

标签: c++ mnemonics


【解决方案1】:

我做了两个关联:

  • 你只能取左值的地址
  • xvalues 就是std::move 表达式

如果两者都不是,那么它可能是一个prvalue。

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

lvalues 和 xvalues 都是 glvalues,而 xvalues 和 prvalues 都是 rvalues。这就是您在实践中需要知道的全部内容。

也许记住 lvaluse、xvalues 和 prvalues 的助记符在底部是单词Lower eXPRessions(它包含 L、X 和 PR)。也许不吧。

【讨论】:

    【解决方案2】:

    您通常只需要知道某事物是左值还是右值。这两类表达方式彼此不同。

    通常情况下,左值表达式指的是会出现一段时间的东西。例如,变量名称是左值,因为变量会一直存在。另一方面,右值表达式通常指的是暂时存在的东西。您只能获取左值的地址,因为到底为什么您需要即将消失的东西的地址?

    现在,在进行这种区分时,您必须考虑到当时编译器所知道的。以函数void foo(const A& a) 为例。在这个函数内部,编译器不知道传递的对象是否是临时对象,所以它只是假设它会一直存在。也就是说,a 是一个左值。即使您可以愉快地将临时对象传递给此函数(使用右值表达式调用它),表达式 a 仍然是左值。

    考虑到这一点,您可以通过是否命名来进一步记住某事物是左值还是右值。在上面的例子中,由于对象被命名为a,它是一个左值。

    现在,对于其余类别,您应该记住下图:

    请注意,左值和右值确实是不同的。然而,右值被分成另外两个类别,xvalues 和 prvalues。此外,xvalues 也被认为是 glvalues 以及所有左值表达式。

    现在知道这些何时出现归结为记住几个案例。

    xvalues 并不常见。它们只出现在涉及转换为右值引用的情况下。以下是所有案例:

    • 返回右值引用的函数的结果
    • 对右值引用的强制转换
    • object.x 如果object 是一个极值
    • object.*member 如果pobject 是一个极值

    根据定义,prvalues 是不是 xvalue 的所有其他类型的右值。例如,从函数中按值返回对象会创建一个临时返回对象。表示该对象的表达式是纯右值。

    类别 glvalue 用于指代所有非纯右值。

    【讨论】:

      【解决方案3】:

      左值可以被认为是“命名”变量或内存位置...右值可以被认为是“未命名”内存位置(即,从函数返回的临时变量)或纯“值” "(即,像一个数字)。

      【讨论】:

      • 不是所有的左值都有名字,至少没有我会描述为名字的任何东西。
      • 只是好奇,你能举个简单的例子吗?我相信所有左值都必须具有某种类型的“内存位置”,可以通过名称访问。
      • 假设std::map<std::string, int> m;m["test"]的名字是什么?
      • 好的,我明白你在说什么,但我看到的方式是你再次通过“名称”访问该内存位置,在这种情况下,你通过 @987654323 进行索引@在m。例如,int foo() { return 5; } 的返回值的“名称”是什么? ...这是“未命名”的一个例子。但在您的情况下,您正在通过命名对象实例访问内存位置,从而使其成为左值。
      • 如果你定义一个宽泛的名字,不是很多右值也有名字吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-03
      • 2021-11-18
      • 1970-01-01
      • 1970-01-01
      • 2017-07-14
      相关资源
      最近更新 更多