2012-02-21 44 views
0

可能重複:
Order of evaluation of arguments using std::cout請解釋這個歧義嗎?

#include<iostream> 
#include<cstdio> 
#include<cstring> 

using namespace std; 

static int series_num; 

void setint(int num) { 
    series_num = num; 
} 

int ser() { 
    series_num = series_num + 23; 
    return series_num; 
} 

int main() { 
    setint(50); 
    cout << ser() << " " << ser(); 
    getchar(); 
    getchar(); 
    return 0; 
} 

返回我96 73

#include<iostream> 
#include<cstdio> 
#include<cstring> 

using namespace std; 

static int series_num; 

void setint(int num) { 
    series_num = num; 
} 

int ser() { 
    series_num = series_num + 23; 
    return series_num; 
} 

int main() { 
    setint(50); 
    cout << ser(); 
    cout << ser() << endl; 
    getchar(); 
    getchar(); 
    return 0; 
} 

返回我73和96

+2

另外查找[「序列點」](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points)這裏在stackoverflow上。 – Benoit 2012-02-21 12:27:25

+1

與以下內容相同:http://stackoverflow.com/questions/7718508/order-of-evaluation-of-arguments-using-stdcout – ArjunShankar 2012-02-21 12:33:32

回答

1

在噸他第一種情況下,你使用一個序列進行兩次調用SER()的調用從右做出向左讓你有96 73.

3
cout << ser() << " " << ser(); 

在這裏,你有沒有它們之間的任意序列點兩次調用ser()
因此,沒有指定什麼將首先評估。

相反,在第二個例子中,行爲是明確定義和可預測的。

+1

每個函數調用和返回都有序列點,所以沒有未定義的行爲。對於'ser'這兩個調用中的哪一個首先發生,因爲在這些調用之間沒有順序點,並且不依賴於另一個調用的結果,所以仍然沒有指定。 – 2012-02-21 12:44:17

+0

@James Kanze:對,謝謝。 – Benoit 2012-02-21 12:45:55

0

在第一種情況

cout << ser() << " " << ser(); 

相當於:

operator<<(cout.operator<<(ser()),"").operator<<(ser()); 

是一個完整的表達。個體運算子的操作數和個別表達式的操作數的評估是不確定的。因此,它沒有定義兩次調用ser()的順序。

你唯一知道的是:

  1. 到SER首先()調用其插入來清點之前執行。
  2. ser()的第二次調用在插入到cout之前執行。
  3. 這是未定義哪個調用ser()之前執行(他們是未序列化)。

因此它是有效的,一個實現返回96 73和不同的實現返回73 96.

此外,在一個程序的執行 期間被評估一次以上的表達,未測序和不定對其子表達的順序評估不需要在不同的評估中一致地執行。這允許如果表達式

cout << ser() << " " << ser(); 

在程序內運行兩次不同的順序被選擇。

在第二個程序中。

cout << ser(); 
cout << ser() << endl; 

是兩個完整的表達式(在兩個單獨的語句中)。在這種情況下,第一條語句在第二條語句之前進行排序,因爲在與每個值計算和與要評估的下一個完整表達式相關的副作用之前,與全表達式相關的每個值計算和副作用都被排序。

結果的唯一可能的結果是73 96