在表达式的左值性中,后缀表达式是比较复杂的一种状况。后缀表达式有不少种,这里讨论的是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;static
};return
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相同。