注:来自某论坛作者的思路。
首先来看这几行代码
int i = 0;
int *ip = &(i++); //错误
int *ip = &(++i); //正确
看到上面的语句,以为两个都是是对的,可是当我用VS2017的编译器试了试之后,才发现第一个取地址确实是错误的语句,具体的提示是:error C2102: “&”要求左值,而第二个取地址是正确的。
也就是说取地址符"&"作用的对象必须是一个左值,左值的概念是什么呢?看一下百度对于C/C++中左值的定义:
左值:
C/C++语言中可以放在赋值符号左边的变量,即具有对应的可以由用户访问的存储单元,并且能够由用户去改变其值的量。左值表示存储在计算机内存的对象,而不是常量或计算的结果。或者说左值是代表一个内存地址值,并且通过这个内存地址,就可以对内存进行读并且写(主要是能写)操作;这也就是为什么左值可以被赋值的原因了。相对应的还有右值:当一个符号或者常量放在操作符右边的时候,计算机就读取他们的“右值”,也就是其代表的真实值。简单来说就是,左值相当于地址值,右值相当于数据值
看完左值的定义就不难理解为什么取地址运算符需要作用在一个左值对象上了。可为什么i++与++i有如此的区别呢?
原因是:i++不是存储在x中的值,他们的具体函数实现请看下面:
1 // 前缀形式: 2 3 int& int::operator++() 4 5 //这里返回的是一个引用形式,就是说函数返回值也可以作为一个左值使用 6 7 { 8 9 //函数本身无参,意味着是在自身空间内增加1的 10 11 *this += 1; // 增加 12 13 return *this; // 取回值 14 15 }
再看这个:
1 //后缀形式: 2 3 const int int::operator++(int) 4 5 //函数返回值是一个非左值型的,与前缀形式的差别所在。 6 7 { 8 9 //函数带参,说明有另外的空间开辟 10 11 int oldValue = *this; // 取回值 12 13 ++(*this); // 增加 14 15 return oldValue; // 返回被取回的值 16 17 }
如上所示,i++ 最后返回的是一个临时变量,而临时变量是右值。