C中的 ++a 和a++
上班 看到有网站推送的邮件
看来n多后有个问题吸引了我下,下面分享下:
请问,(a++)++,(++a)++,++(a++),++(++a)能够编译通过么?如果可以,那么运行之后a的值是多少?如果不能,为什么?
这个看起来很简单的问题,我以为一次性猜出答案,后来发现我错了!
这个其实是和编译器有关的。
那么以VS2008为例来说吧~
上述代码的编译结果:
1>------ 已启动生成: 项目: test30, 配置: Debug Win32 ------ 1>正在编译... 1>main.cpp 1>g:\workspace\exercise\cppprimer\test30\test30\main.cpp(8) : error C2105: “++”需要左值 1>g:\workspace\exercise\cppprimer\test30\test30\main.cpp(12) : error C2105: “++”
即(a++)++;和++(a++);会编译出错,其他的通过编译。原因如下:
后置++返回右值,而前置++返回左值。
其实,看下前置和后置++的实现就知道的很清楚了,这是从《C++ Primer(第三版)》上摘下来的一段代码,是实现对复数对象的操作符重载:
前置: inline complex<double>& operator++(complex<double> &cval) { return cval += complex<double>(1); } 后置: inline complex<double> operator++(complex<double> &cval,int) { complex<doble> oldval = cval; cval += complex<double>(1); return oldval; }
你会发现,前置++是返回的左值,而后置++返回的是一个局部变量,是右值。
再举一个例子,假设有一个类Age,描述年龄。该类重载了前置++和后置++两个操作符,以实现对年龄的自增。
1. class Age 2. { 3. public: 4. 5. Age& operator++() //前置++ 6. { 7. ++i; 8. return *this; 9. } 10. 11. const Age operator++(int) //后置++ 12. { 13. Age tmp = *this; 14. ++(*this); //利用前置++ 15. return tmp; //注意:返回的是临时对象 16. } 17. 18. Age& operator=(int i) //赋值操作 19. { 20. this->i = i; 21. return *this; 22. } 23. 24. private: 25. int i; 26. };
从上述代码,我们可以看出前置++和后置++,有4点不同:
1. 返回类型不同
2. 形参不同
3. 代码不同
4. 效率不同
返回值类型的区别前置++的返回类型是Age&,后置++的返回类型const Age。这意味着,前置++返回的是左值,后置++返回的是右值。
左值和右值,决定了前置++和后置++的用法。
1. int main() 2. { 3. Age a; 4. 5. (a++)++; //编译错误 6. ++(a++); //编译错误 7. a++ = 1; //编译错误 8. (++a)++; //OK 9. ++(++a); //OK 10. ++a = 1; //OK 11. }
a++的类型是const Age,自然不能对它进行前置++、后置++、赋值等操作。
++a的类型是Age&,当然能对它进行前置++、后置++、赋值等操作。
转载于:http://www.dewen.org/q/7318/?utm_source=weekly_32607189_31&utm_field=5&utm_id=7