基础概念
在文章开头,先用最简洁的方式区分i++与++i:i++表示先引用,后自增;++i则是先自增后引用。
i++与++i的效率比较需分为以下两种情况讨论:
内建数据类型
对于内建数据类型(int\float\double
等基本类型),i++与++i在单独使用时(即自增结果未被使用),效率相等。当i++与++i的结果被使用时,其效率也无差别,只不过由于自增运算的先后顺序不同,导致传值的结果不同。
下面,在vs2010中验证以上想法:
int main(){
int i = 0;
//00BCBB3E mov dword ptr [i],0
int x = 0;
//00BCBB45 mov dword ptr [x],0
i++;
/*
00BCBB4C mov eax,dword ptr [i]
00BCBB4F add eax,1
00BCBB52 mov dword ptr [i],eax
*/
++i;
/*
00BCBB55 mov eax,dword ptr [i]
00BCBB58 add eax,1
00BCBB5B mov dword ptr [i],eax
*/
x = i++;
//先将i的值赋给x,再自增
/*
00BCBB5E mov eax,dword ptr [i]
00BCBB61 mov dword ptr [x],eax
00BCBB64 mov ecx,dword ptr [i]
00BCBB67 add ecx,1
00BCBB6A mov dword ptr [i],ecx
*/
x = ++i;
//先自增,再将i的值赋给x
/*
00BCBB6D mov eax,dword ptr [i]
00BCBB70 add eax,1
00BCBB73 mov dword ptr [i],eax
00BCBB76 mov ecx,dword ptr [i]
00BCBB79 mov dword ptr [x],ecx
*/
return 0;
}
由上述代码可以看出,i++与++i在单独使用时被vs2010中被解释为三条汇编指令。在结果被使用的情况下,都被解释为五条汇编指令,效率相当。由此引申到,在内建数据类型的for循环中,for(int i=0; i<n; i++)
与for(int i=0; i<n; ++i)
效率相同。
自定义数据类型
对于自定义数据类型(包括STL),前缀自增(++iterator)可以返回对象的引用,返回的结果为左值。而后缀自增(iterator++)必须返回对象的值,返回结果为临时变量,是右值。由于后缀式(iterator++)需要增加复制和析构的开销,其效率比前缀式(++iterator)低。
同样地,我们在vs2010中验证此想法:
int main(){
vector<int> test;
test.push_back(0);
test.push_back(1);
test.push_back(2);
vector<int>::iterator iter=test.begin(), iter1;
++iter;
/*
00A9BB53 lea ecx,[ebp-38h]
00A9BB56 call std::_Vector_iterator<std::_Vector_val<int,std::allocator<int> > >::operator++ (0A8982Fh)
*/
iter++;
/*
00A9BB5B push 0
00A9BB5D lea eax,[ebp-154h]
00A9BB63 push eax
00A9BB64 lea ecx,[ebp-38h]
00A9BB67 call std::_Vector_iterator<std::_Vector_val<int,std::allocator<int> > >::operator++ (0A8982Ah)
00A9BB6C lea ecx,[ebp-154h]
00A9BB72 call std::_Vector_iterator<std::_Vector_val<int,std::allocator<int> > >::~_Vector_iterator<std::_Vector_val<int,std::allocator<int> > > (0A894D8h)
*/
iter=test.begin();
iter1 = ++iter;
/*
00A9BBBA lea ecx,[ebp-38h]
00A9BBBD call std::_Vector_iterator<std::_Vector_val<int,std::allocator<int> > >::operator++ (0A8982Fh)
00A9BBC2 push eax
00A9BBC3 lea ecx,[ebp-4Ch]
00A9BBC6 call std::_Vector_iterator<std::_Vector_val<int,std::allocator<int> > >::operator= (0A89DBBh)
*/
iter1 = iter++;
/*
00A9BBCB push 0
00A9BBCD lea eax,[ebp-12Ch]
00A9BBD3 push eax
00A9BBD4 lea ecx,[ebp-38h]
00A9BBD7 call std::_Vector_iterator<std::_Vector_val<int,std::allocator<int> > >::operator++ (0A8982Ah)
00A9BBDC mov dword ptr [ebp-180h],eax
00A9BBE2 mov ecx,dword ptr [ebp-180h]
00A9BBE8 mov dword ptr [ebp-184h],ecx
00A9BBEE mov byte ptr [ebp-4],4
00A9BBF2 mov edx,dword ptr [ebp-184h]
00A9BBF8 push edx
00A9BBF9 lea ecx,[ebp-4Ch]
00A9BBFC call std::_Vector_iterator<std::_Vector_val<int,std::allocator<int> > >::operator= (0A89DBBh)
00A9BC01 mov byte ptr [ebp-4],2
00A9BC05 lea ecx,[ebp-12Ch]
00A9BC0B call std::_Vector_iterator<std::_Vector_val<int,std::allocator<int> > >::~_Vector_iterator<std::_Vector_val<int,std::allocator<int> > > (0A894D8h)
*/
return 0;
}
由上述代码可以明显看出,对于自定义数据类型,无论是自增结果是否被使用,后缀自增的效率都比前缀自增低。