關於++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
 
int t = i;
 

這步,所以++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.二者都對i1,但處理的順序不同。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.   編譯器函數實參的表達式處理順序是從右向左。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章