[C++]關於i++和++i的學習
今天在論壇上無意中看到有人問關於i++和++i的問題,感覺自己也不怎麼熟悉,就仔細看了一下。感覺有位大俠的回覆相當不錯,很有特色,把問題講得很明白,受教了。
這裏摘錄一下,學習學習!
--------------------------------------------------------------------------------------------------------
關於++i和i++的區別,如果用一個函數來說明,則它們分別等價於下面兩個函數:
++i:
C/C++ code
int ppi(int & i)
{
i = i + 1;
return i;
}
i++:
C/C++ code
int ipp(int & i)
{
int t = i;
i = i + 1;
return t;
}
顯見,兩個函數都將i的值加了1,但返回的值卻不一樣。另外,ipp比ppi多了
C/C++ code
這步,所以++i的效率要比i++高一點。
--i和i--與此同理。
第二個問題: cout和printf多個輸出時++i和i++的區別?
就是關於
cout<<i<<” “<<++i<<endl;與cout<<i<<” “<<i++<<endl;的區別
cout<<i<<” ”<<++i<<endl;與cout<<i<<” ”; cout<<++i<<endl;的區別
下面以一個例程來說明這個問題:
C/C++ code
#include <stdio.h>
#include <iostream.h>
int main(void)
{
int i = 0;
cout << "Test execute order: " << endl
<< "cout: "
<< i << ", " << ++i << endl;
i = 0;
printf("printf(): %d, %d/n", i, ++i);
return0;
}
這段代碼在VC6.0、BC3.1下的執行結果是:
Test execute order:
cout: 1, 1
printf(): 1, 1
cout < < 實際上是執行了cout對象的重載操作符( < <)函數:
C/C++ code
ostream& operator<<( datatype );
這裏的datatype是隻相應的數據類型。該函數的調用之所以能寫成cout < < "a" < < 3 < < "b" < < endl;這種拼接輸出的形式,是因爲它返回的是cout這個ostream對象本身,而返回的cout對象繼續調用上面函數對下一個操作數進行輸出,如此反覆,直到該語句結束(當然,遇到刷新緩衝區的命令時還得先刷新)。由此可知,cout的執行順序是從左到右的。
至於爲什麼i的值先被改變了呢?那是因爲,C++標準對表達式的求解順序不作規定,交給編譯器決定。因此,各個編譯器的實現也有點差異。例如,上面那個例程如果在gcc(g++)下執行的話,結果則是:
Test execute order:
cout: 0, 1
printf(): 1, 1
由此可知,VC、BC和gcc(g++)對這種拼接形式的表達式求解順序不一樣,後者是從左到右,前者是保持跟函數的順序一樣,即都是從右到左。而兩者在對函數實參的表達式求解順序卻都是一樣,即都是從右到左(看printf()的輸出)。
因此。編程忠告不建議在同一個表達式裏面同時修改同一個變量。
在平臺:sparc-sun-solaris2.10-g++ (GCC) 4.0.3 (gccfss),結果是:
Test execute order:
cout: 0, 1
printf(): 1, 1
在平臺:g++ (GCC) 3.4.6 20060404 (Red Hat 3.4.6-3),結果是:
Test execute order:
cout: 1, 1
printf(): 1, 1
這恰恰再次印證了“表達式求值順序未定義”結論的正確性。
總結一下:
關於i++和++i:
1.二者都對i加1,但處理的順序不同。i++先對i作相關運算,然後加1。++i先遞增,然後再進行相關運算。
2.單獨使用時,++i的效率要比i++效率高。
關於cout<<i<<i++<<endl;和cout<<i<<++i<<endl;有:
1. Cout是對<<運算符的重載,返回的是cout這個ostream對象本身。<<連續使用時,返回的cout對象繼續調用上面函數對下一個操作數進行輸出,如此反覆,直到該語句結束。因此,cout執行順序是從左到右。
2. C++標準對表達式的求解順序不作規定,根據編譯器不同而不同。因此,在不同的編譯器環境下,cout<<i<<++i<<endl;輸出並不總是按照cout從左到右的順序執行。
3. 編譯器函數實參的表達式處理順序是從右向左。