为了账号安全,请及时绑定邮箱和手机立即绑定

为什么++ i被认为是l值,而i ++却不是?

为什么++ i被认为是l值,而i ++却不是?

C++
繁花如伊 2019-11-11 15:46:44
为什么++ i是l值而i ++不是?
查看完整描述

3 回答

?
肥皂起泡泡

TA贡献1829条经验 获得超6个赞

正如另一个回答者已经指出的,为什么++i是左值是将其传递给引用。


int v = 0;

int const & rcv = ++v; // would work if ++v is an rvalue too

int & rv = ++v; // would not work if ++v is an rvalue

第二条规则的原因是,当引用是对const的引用时,允许使用文字初始化引用:


void taking_refc(int const& v);

taking_refc(10); // valid, 10 is an rvalue though!

您为什么要问我们为什么要引入右值。好了,在为以下两种情况建立语言规则时会出现这些术语:


我们想要一个定位器值。那将代表一个包含可以读取的值的位置。

我们要表示一个表达式的值。

以上两点摘自C99标准,其中包括这个非常好的脚注,非常有帮助:


[名称“左值”最初来自赋值表达式E1 = E2,其中左操作数E1必须是(可修改的)左值。最好将其表示为对象“定位器值”。在本国际标准中有时称为“ rvalue”的内容称为“表达式的值”。]


定位器的值称为lvalue,而评估该位置所得到的值称为rvalue。根据C ++标准,这也是正确的(谈论从左值到右值的转换):


4.1 / 2:由左值表示的对象中包含的值是右值结果。


结论

使用上述语义,现在很清楚为什么i++不是左值而是右值。因为返回的表达式不再位于i(它已递增!),所以它只是可能值得关注的值。修改返回的值是i++没有意义的,因为我们没有可以再次读取该值的位置。因此,标准说它是一个右值,因此它只能绑定到对常量的引用。


但是,相反,所返回的表达式++i是的位置(左值)i。像in那样引发从左值到右值的转换int a = ++i;将读取其中的值。或者,我们可以对其进行参考,然后稍后读出该值:int &a = ++i;。


还请注意生成右值的其他情况。例如,所有临时变量都是右值,二进制/一元+和负号的结果以及所有不是引用的返回值表达式。所有这些表达式都不位于命名对象中,而是仅带有值。这些值当然可以由不恒定的对象备份。


下一个C ++版本将包括所谓的rvalue references那个,即使它们指向nonconst,也可以绑定到右值。基本原理是能够“窃取”那些匿名对象的资源,并避免使用副本进行复制。假设一个类类型的前缀++(返回Object&)和后缀++(返回Object)都已重载,则以下内容将首先导致复制,而在第二种情况下,它将从右值中窃取资源:


Object o1(++a); // lvalue => can't steal. It will deep copy.

Object o2(a++); // rvalue => steal resources (like just swapping pointers)


查看完整回答
反对 回复 2019-11-11
?
桃花长相依

TA贡献1860条经验 获得超8个赞

其他人已经解决了后增量和前增量之间的功能差异。


就左值而言,i++由于它不引用变量,因此无法分配给它。它指的是计算值。


在分配方面,以下两种方式都没有意义:


i++   = 5;

i + 0 = 5;

因为pre-increment返回对增量变量的引用而不是临时副本,所以它++i是一个左值。


当您要增加迭代器对象(例如,STL中的对象)之类的东西可能比int的权重大得多时,出于性能原因而首选pre-increation成为一个特别好的主意。


查看完整回答
反对 回复 2019-11-11
  • 3 回答
  • 0 关注
  • 479 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信