【问题标题】:How is a rvalue dereferenced?如何取消引用右值?
【发布时间】:2016-03-21 03:30:43
【问题描述】:

前缀运算符返回对象 本身作为左值。后缀运算符返回对象原始值的副本 作为右值。

所以在*a++ 这样的语句中,a 正在递增,并且 a 的原始值的副本作为右值返回,但来自 microsoft c++ 语言对左值和右值的参考

右值是一个临时值,不会在使用它的表达式之外持续存在

并举个例子

// lvalues_and_rvalues1.cpp
// compile with: /EHsc
#include <iostream>
using namespace std;
int main()
{
   int x = 3 + 4;
   cout << x << endl;
}

在这个例子中,x 是一个左值,因为它在定义它的表达式之外仍然存在。表达式 3 + 4 是一个右值,因为它的计算结果是一个临时值,该值不会持续超出定义它的表达式。

我的问题:
1) 从*a++ 返回的右值是什么,以便可以取消引用?
2)我误解了任何概念吗?
提前致谢!

【问题讨论】:

  • 你的第一句话是假的,例如+x 是一个右值。也许它只是在谈论++-- 运算符。
  • 第二个引用也是错误的:rvalue是一个表达式类别,不是一个值。 (命名有点混乱)。 3 + 4 是一个右值,但第三个引号应该说“它不会在表达式之外持续存在,因为它是一个临时值”,而不是相反。
  • 我的意思是这句话实际上是不正确的——没有指责你抄写错误或任何事情
  • Here 是一个描述 rvalue 含义的页面。如果您尝试从该 MSDN 页面学习,您会感到困惑,这不足为奇
  • @psraganvesh 是的,这是一种表达方式。但请记住,对于类类型的右值(即指定临时对象的右值),您可以获得一个标识该临时对象位置的左值。 (例如,如果对象具有通过引用执行 return *this; 的成员函数)。右值是表达式的属性,而不是对象的属性。如果您指的是临时对象,请说“临时对象”。

标签: c++ dereference lvalue rvalue


【解决方案1】:

前缀运算符将对象本身作为左值返回。后缀运算符将对象原始值的副本作为右值返回。

错了!嗯,大部分是这样。如果引用是在谈论 all 前缀/后缀运算符,那么它完全是错误的。但是,如果它是在谈论 ++-- 前缀/后缀对,那么它是正确的。

现在,考虑到这一点...

从 *a++ 返回的右值是什么,以便可以取消引用?

假设a 是某种指针,a++ 递增a 并产生一个右值,该右值包含a 在递增之前的值。后缀和前缀形式的递增和递减运算符++-- 都需要一个左值作为它们的运算符。这是因为右值是临时的,也就是说,它们的范围受它们出现的表达式的限制,所以这些运算符对它们几乎没有意义。请记住,这些运算符不仅inspect/read,而且change/写入变量本身。

一元 * 运算符接受一个指针(类似)对象并取消引用它,从而产生一个在其中找到的左值。它适用于右值和左值指针。这是因为* 可以被认为是一种“被动”运算符。它不会更改/写入指针本身,而是取消引用它并返回指针存储的地址处的左值对象,其地址当然是包含在指针。由于* 需要的只是指针对象中包含的内存地址,而指针本身的地址(如果有的话)在这里是无用的,* 对右值和左值都有意义。

你可以认为*“需要一个右值”,并且“在必要时可以将左值用作右值”,如果它更清楚(或混淆?)事情的话。

【讨论】:

  • 因此,在增量之前的 a 值是一个内存位置,只要 '*' 有一个内存位置,要么是左值(具有内存位置的对象),要么是右值(不代表占用一些对象的表达式内存中可识别的位置。)可以取消引用以获取存储在地址中的值
  • @psraganvesh:没错。
  • 感谢您的宝贵时间!
【解决方案2】:

*a++ 等价于:

auto temp = *a;
a++;
// Use the value of temp here

除非您只能引用一次该值,而 temp 您可以引用多次。

【讨论】:

  • 这是真的,但我不认为它解决了 OP 的问题(这似乎是:为什么 * 可以应用于右值)。
  • 是的。 a 可以是一个指针,也可以是任何重载operator * 的类的对象。但如果问题是“为什么* 可以应用于a++?”,答案必须是“因为* 可以应用于a。”
  • @JamesRoot 否。后缀++ 运算符在使用后增加a 的值。在这里,使用它是使用 * 运算符取消引用它。所以顺序是*a,然后是a++
  • 没错,但a 是左值,a++ 是右值,OP 似乎认为将* 应用于每个类别有不同的规则
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-06
  • 2011-07-13
  • 2011-12-13
  • 1970-01-01
  • 2019-10-12
  • 2014-05-15
  • 2013-04-28
相关资源
最近更新 更多