x=x++带来的困惑。。。
来源:互联网 发布:手机定位软件修改 编辑:程序博客网 时间:2024/05/27 01:38
今天微软实习生笔试,有一个题目,本来我认为没有什么值得考虑的,结果出来同学一讨论,出现一边倒的结果,当然我不是那一边的,我就想当郁闷呀。
问题主要是:
int x = 10;x = x++;cout<<x<<endl;我想也没想,这结果当然是10了,可以同学回来都说是11,然后再机器上一测试,结果果然是11,我感觉整个人生观被颠覆了。
我清楚的记得后置形式自增/自减,的计算顺序是:先保存操作数原来的值,然后对操作数进行自增/自减操作,然后返回之前保存的操作数的值即未进行自增/自减操作的值。在C++ Primer第四版 P140也是这么说的:
Fig 1
由C++ Primer说法可知,之所以必须先保存操作数原来的值,是因为在返回自增表达式结果之前,会对操作数进行自增运算。
但现在的结果变成了把自增操作放到了复制操作的后面,下面是反汇编的结果:
int x = 10;0041191D mov dword ptr [ebp-14h],0Ah x = x++;00411924 mov eax,dword ptr [ebp-14h] 00411927 mov dword ptr [ebp-14h],eax 0041192A mov ecx,dword ptr [ebp-14h] 0041192D add ecx,1 00411930 mov dword ptr [ebp-14h],ecx
在Fig 1中有这么一句话:对于int型对象和指针,编译器可优化点这项额外工作,但是对于更多的复杂迭代器 类型,这种额外工作可能会花费更大的代价,
所以我做了下面的测试:
vector<int> y; for (int i = 0; i < 10; ++i) { y.push_back(i); } vector<int>::iterator itr = y.begin(); while(itr != y.end()) { itr = itr++; cout<<*itr<<endl; }如果说和上面的x一样的话,迭代器解引用会输出y中的所有元素(当然这里代码有点问题,就是itr会指向end,会出错,但不影响测试)。但是结果是死循环,始终输出0,这也就表明:itr = itr++的计算顺序是先保存itr的值,然后对itr进行++操作,然后把事先保存的itr的值赋给itr。
下面是反汇编结果的代码
itr=itr++;00411A16 push 0 00411A18 lea eax,[ebp-13Ch] 00411A1E push eax 00411A1F lea ecx,[ebp-5Ch] 00411A22 call std::_Vector_iterator<int,std::allocator<int> >::operator++ (41100Ah) 00411A27 mov dword ptr [ebp-164h],eax 00411A2D mov ecx,dword ptr [ebp-164h] 00411A33 mov dword ptr [ebp-168h],ecx 00411A39 mov byte ptr [ebp-4],3 00411A3D mov edx,dword ptr [ebp-168h] 00411A43 push edx 00411A44 lea ecx,[ebp-5Ch] 00411A47 call std::_Vector_iterator<int,std::allocator<int> >::operator= (41100Fh) 00411A4C mov byte ptr [ebp-4],1 00411A50 lea ecx,[ebp-13Ch] 00411A56 call std::_Vector_iterator<int,std::allocator<int> >::~_Vector_iterator<int,std::allocator<int> > (411064h)由反汇编的结果可以知道,是先保存itr的值,然后对itr进行++操作,然后把事先保存的itr的值赋给itr。
所以可知对于int型对象和指针,编译器进行了优化,直接把x的值赋给了表达式左边的值,然后对x进行自增,而对于迭代器类型,并没有进行优化;
所以说:x从C标准定义的结果应该是10,而不是11。
Apr 6, 2013 @lab
博客内容修改:
C/C++标准除了对操作符:&&,||, ?:,,(逗号操作符)这四个操作符定义了求值顺序,对于其他的操作符都未定义求值顺序,所以上面所讨论的问题,只是编译器的实现问题,标准从未定义过,具体可参考C++ Primer P149 ,和http://bbs.csdn.net/topics/370153775,谢谢1楼和2楼的提醒
修改时间:Apr 7, 2013
- x=x++带来的困惑。。。
- ls带来的困惑
- scala private[x]困惑
- spring2.x与spring3.x区别带来的问题
- x=x++的问题
- x=x+1,x+=1,x++的区别
- Mac OS X 10.11升级带来的 cocoapods问题
- 解决OS X 10.11 升级 cocoapods带来的问题
- 【NodeJS】express3.x所带来的github警告
- 能力的困惑,空降兵带来的烦恼!
- 加载 mswin.vim 带来的困惑
- NRV优化所带来的困惑
- 解决OS X 10.11(OS X EL Capitan) 升级 cocoapods带来的问题(最新版)
- x=x&(x-1)
- x=x&(x-1)
- x = x&(x-1)
- x = x&(x-1)
- x+=y与x=x+y的区别
- <table>合并内边框
- 文学电子书更新2013年4月6日 16:56:25
- iOS视频播放 [MPMoviePlayerController]
- 数组和链表的区别
- 浅谈字符编码方式与python的中文编码(一)
- x=x++带来的困惑。。。
- tomcat 6.0配置
- 深入理解sizeof
- 网络编程—03
- Spring C3P0 配置文件
- linux内核__define_initcall分析
- 如何提问题
- c3p0配置文件详细说明
- Linux 中history 下的命令