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

偶尔善良 提交于 2020-02-29 05:08:17

在表达式的左值性中,后缀表达式是比较复杂的一种情况。后缀表达式有很多种,这里讨论的是E1.E2和E1->E2形式的后缀表达式。

4.1  E1.E2形式的后缀表达式

        若E2为静态数据成员或引用数据成员,无论E1的左值性如何,E1.E2的结果都是左值;若E2为非静态非引用数据成员,C和C++标准都规定如果E1为左值,则E1.E2也是左值;当E1为右值时,从原理上说,右值对象的一部分也应该是一个右值,因此在C中,无论E2的左值性如何,E1.E2皆为右值;那么C++中的结果又如何呢?按道理应该顺理成章也为右值吧,但令人惊讶的是,C++98和C++2003都没有对此作出规定!因此在C++98和C++2003中,无论编译器将这种情况作为左值或右值都没有违反标准。这种情况显然是一个漏洞,在C++新标准C++11的制定过程中,WG21的专家在其Defect Reports中承认了这一点,并在C++11中将结果修正为一个prvalue(pure rvalue,纯右值)。

struct A

{

    A( int& i ) : r( i ){}

    static int k;

    int &r;

    int j;

};

int A::k = 10;

A foo( int& r ){ A a( r ); return A; }

......

int i = 20;

A a( i );

a.k = 30;               //静态成员,左值

a.r = 40;               //引用成员,左值

a.j = 50;               //a是左值,所以a.j是左值

foo( i ).k = 60;        //静态成员,左值,虽然foo( i )返回一个右值

foo( i ).r = 70;        //引用成员,左值,虽然foo( i )返回一个右值

foo( i ).j = 80;        //foo( i ).j左值右值都合法,因为标准没有规定

E2为函数成员。若E2为静态成员函数,无论E1的左值性如何,结果都为左值。若E2为非静态成员函数,如3.1节所述,由于非静态成员函数不是左值,因此无论E1的左值性如何,E1.E2的结果都是右值。

4.2  E1->E2形式的后缀表达式

        由于C中的右值地址无法获得,因此C中的E1总是指向左值的指针,所以C中的E1->E2后缀表达式的结果总是左值;但C++有很大不同,C++中的E1->E2后缀表达式是转换为等价形式(*E1).(E2)进行计算的,因此E1->E2的左值性与E1.E2相同。

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