其實這個問題,百度的話,有一大堆的參考資料,但是,在這裡,我產生了一些困惑,他們所分析的結果,和我的測試代碼不一致,這讓我糾結了,所以,再次的寫一下這個問題,順順思路。
我的測試環境:系統:Windows7 32bit,編程平台:Qt 5.3.1 (MSVC 2010,32bit)
首先說一下比較被大眾所認可的結果:
(1)在自定義的數據類型的時候,因為前綴式(++i)可以返回對象的引用,而後綴式(i++),必須返回對象的數值,所以,導致在大的對象的時候產生了較大的復制開銷,引起效率降低。所以,使用自定義的數據類型的時候,使用前綴式(++i)效率更好一些;
(2)如果是內置類型的,如int,效率是一樣的。
(3)c++Primer上面有說:對於老舊的編譯器++i效率好,對於好的編譯器i++被優化了(效率一樣)。表示該用哪個用哪個。
我的測試代碼:
#include <iostream> using namespace std; //struct(1 data member) struct oj { int j; }a; //(2 data members) class class oo { public: oo():a(0),b(0){} oo operator ++()//Prefix plus { ++a; ++b; return *this; } oo operator ++(int)//suffix plus { oo temp(*this); a++; b++; return temp; } private: int a; int b; }; int main() { int i=0; int x=0; //Built-in data types i++; ++i; x=i++; x=++i; //struct(1 data member) a.j = 0; a.i = 0; a.j++; ++a.j; x = a.j++; x = ++a.j; //(2 data members) class oo o,ox; o++; ++o; ox = o++; ox = ++o; return 0; }
最接近機器語言的匯編
(1)先分析內建的數據類型:
對於內建的數據類型,單獨使用i++和++i是沒有效率區分的。但是,表達式中的i++和++i是有區別的,如上圖所示,所以對於內建的表達式中的,根據需求,含有++i的表達式的效率要好一些。(注意,這裡我強調的是整個表達式的效率。而非單純的i++ and ++i.)
(2)自定義的數據類型(結構體):
如測試代碼,這裡使用了結構體,包含一個數據成員。
對於一個結構體(包含有一個數據成員)的自定義數據類型而言,單獨的a.j++ and ++ a.j的效率是一樣的,沒有什麼可爭論的。但是,對於表達式的中的 x = a.j++ and x = ++a.j,這個表達式的效率,結果確出現了和“自定義的數據類型中,++i的效率更好”的違背。原因圖片中已經解釋過了,所以,對於表達式中含有自增和自減運算符的,在討論表達式的效率的時候,不能單純的使用理論依據,還應該考慮自己的平台環境,編譯器的指令集系統,這裡我想到了精簡指令集和復雜指令集。
(3)自定義數據類型(類,2個數據成員,重載++運算符)
對於類對象的自增運算,我們重載了運算符。從匯編代碼來看,不管是單獨使用,還是含有自增運算符的表達式,O++操作,因為有入棧和出棧操作,所以,顯得效率有些不佳。但是,在這裡,我們完全沒有考慮重載函數的運行效率,這裡只是顯示了函數的調用。其實,這裡不用深究重載函數的效率了,單從C++語言就可以看出來。前綴的++i的重載函數的效率更好一些。
2個重載函數的匯編代碼對比(左邊為++i前綴的重載,右邊為i++後綴的重載):
自我總結:
這裡,我不想說,i++ 和 ++i的效率哪一個更好,通過上面的測試代碼,我們可以發現,對於不同的環境,不同的數據結構會有不同的效率。我想說的是,通過發現一個問題,然後尋找答案,質疑答案,驗證答案的這個過程,讓我學會了不少東西。也許我的驗證方法是不科學的,但是從中我認真的對待過,從中,學會了閱讀匯編代碼,這使我更加深刻的理解了機器對於程序的運行機制是什麼樣的。認真對待問題,你會從中收獲很多的。
如果有面試官問你這樣的問題的話,可以如下回答:
內建的數據類型時,效率一樣。
但是,在自定義的數據類型的時候,因為前綴式(++i)可以返回對象的引用,而後綴式(i++),必須返回對象的數值
所以,導致在大的對象的時候產生了較大的復制開銷,引起效率降低。
所以,使用自定義的數據類型的時候,使用前綴式(++i);
同時,真的需要在細節上提高自己程序效率的話,你可以寫個簡單的測試用例,測試一下。因為在自己的平台上測試,相對准確一些。沒必要,像我這麼糾結。