基礎(chǔ)概念
在文章開頭,先用最簡潔的方式區(qū)分i++與++i:i++表示先引用,后自增;++i則是先自增后引用。
i++與++i的效率比較需分為以下兩種情況討論:
內(nèi)建數(shù)據(jù)類型
對于內(nèi)建數(shù)據(jù)類型(int\float\double等基本類型),i++與++i在單獨使用時(即自增結(jié)果未被使用),效率相等。當(dāng)i++與++i的結(jié)果被使用時,其效率也無差別,只不過由于自增運算的先后順序不同,導(dǎo)致傳值的結(jié)果不同。
下面,在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中被解釋為三條匯編指令。在結(jié)果被使用的情況下,都被解釋為五條匯編指令,效率相當(dāng)。由此引申到,在內(nèi)建數(shù)據(jù)類型的for循環(huán)中,for(int i=0; i<n; i++)與for(int i=0; i<n; ++i)效率相同。
自定義數(shù)據(jù)類型
對于自定義數(shù)據(jù)類型(包括STL),前綴自增(++iterator)可以返回對象的引用,返回的結(jié)果為左值。而后綴自增(iterator++)必須返回對象的值,返回結(jié)果為臨時變量,是右值。由于后綴式(iterator++)需要增加復(fù)制和析構(gòu)的開銷,其效率比前綴式(++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;
}
由上述代碼可以明顯看出,對于自定義數(shù)據(jù)類型,無論是自增結(jié)果是否被使用,后綴自增的效率都比前綴自增低。