C/C++左值性精髓(二)哪些表达式是左值,哪些是右值?----右值表达式

陌路散爱 提交于 2020-02-29 05:53:56

C对于右值的定义是表达式的值,C中所有完整表达式的结果都是右值。所谓完整表达式(full expression),指的是这样的表达式,它不是其它表达式或声明符的一部分。包括条件表达式和逗号表达式等等都不产生左值,而子表达式计算产生的中间结果或临时对象,很多人以为都是右值,但实际上,它们不一定是右值。例如:

int a[ 5 ] = { 1, 2, 3, 4, 5 };

int *p = a;

*p = 2;                         /* A */

a[ 1 ] = 3;                     /* B */

*p;                             /* C */

a[ 1 ];                         /* D */

A和B中的*p和a[ 1 ]都是内置赋值运算符的子表达式,虽然都是中间结果,但显然都属于左值表达式;只有当它们作为完整表达式时,如C和D中的*p和a[ 1 ]所示,都会进行最后的左值转换,使得结果皆为右值。这个现象的本质,是由于C将所有完整表达式的结果一律进行最后的从左值到右值的转换,这个行为可以理解为一个完全求值的过程(完全求值不是标准术语)。

        但C++的完整表达式并不要求进行完全求值,是否保留左值性视需要而定,这个“需要”是什么?其实是C++某些运算符的强制规定,例如内置赋值运算符、前置增量和前置减量运算符等等,这类运算符的结果被强制规定为左值,对于条件运算符,只有第二和第三表达式皆为左值且类型相同时才保证结果为左值。原因无它,仅仅规定而已。

右值是不是对象?由于左值要求一个对象,因此比较容易产生的误解是,右值不是对象。但,如果函数返回一个结构呢?

struct S { int a; };

struct S fun( void ){ struct S s; ...; return s }

由于POD结构属于聚集,不是标量,因而POD结构不是一个值,标量才被视为一个值。上述代码中,fun返回了一个POD结构S的临时对象,而且是一个右值,即无论C还是C++都存在右值对象,。因此,右值只是不要求是对象,并非不能是对象。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!