练习 1-4. a+++++b的含义是什么?
事实上答案是很简单的,((a++)++)+b, 后来在参看答案的时候发现了这样一句话:这个式子从语法上面来说是不正确的,a++的结果不能作为左值。
对于++运算,前缀,后缀和别人谈得也是很多的,不过对于左值却谈得很少,因此决定对这个问题作一下了解。
首先我们来看看什么是左值。
左值 (lvalue):左值表达式是对一个变量存储的引用,变量存储表达式称为左值表达式,我们可以简单的理解为可以被赋值的表达式。
我们先来看看这个程序:
#i nclude <stdio.h>
#i nclude <stdlib.h>
int main( )
{
int a = 1 ;
(a++)++ ;
++(++a) ;
(++a)++ ;
++(a++) ;
return 0 ;
}
编译的时候是不能通过的:error C2105: '++' needs l-value, 也就是说++运算符缺需要一个值参与++运算,我们知道++运算符是单目运算符,它缺少了一个值参与这个运算,当然就是不能编译通过的了。通过编译我们还可以知道问题出在
(a++)++ ; 和++(a++) ; 这两个表达式上面。而这个原因是因为++a返回的值是左值,而a++返回的值不是左值。而导致这个原因的罪魁祸首在于c/c++对于递增运算的定义:
返回引用:
type& type::operator++( )
{
this.value += 1;
return *this;
}
返回值:
type& type::operator++( )
{
type co(this); this.value += 1;
return co;
}
在运算过程中,先将对象修改然后返回对象的运算称为前增量运算符,在运算符重载中采取返回对象引用的方式,否则称为后增量运算符,在运算符重载中采取返回对象值的方式。返回引用的函数是可以当左值的。
我们现在来做一个测试:定义一个函数max( int x , int y ) ; 看看在返回值的时候和返回引用的时候会有什么区别:
#i nclude <iostream>
using namespace std ;
int& max( int x , int y ) ;
void main()
{
int temp = 0 ;
temp = max(2,3) = 4 ;
cout << temp << endl ;
}
int& max( int x , int y )
{
return x>y?x:y ;
}
这个程序中我们定义了一个max函数,返回两个整型数中比较大的一个,但是这里有一个比较难以理解的句子: temp = max(2,3) = 4 ; 实际上,这就使因为max()返回的是一个引用,可以被赋值的原因,我们现在把这个函数改成返回值的:
#i nclude <iostream>
using namespace std ;
int max( int x , int y ) ;
void main()
{
int temp = 0 ;
temp = max(2,3) = 4 ;
cout << temp << endl ;
}
int max( int x , int y )
{
return x>y?x:y ;
}
现在就不能编译通过了:error C2106: '=' : left operand must be l-value
参考资料:
Andrew Koening . C Traps and pitfalls. 人民邮电出版社. 2002.13,129
Scott Meyers . Effctive c++ . 华中科技大学出版社. 2003. 64-68