2013-08-25 157 views
14

我有以下代碼。這個輸出的原因是什麼?

int x=80; 
    int &y=x; 
    x++; 
    cout<<x<<" "<<--y; 

輸出結果是80 80.我不明白怎麼回事。我認爲x的輸出是81,但我對y沒有任何瞭解。參考變量如何受減量運算符影響。有人可以解釋嗎?

+1

也許這個問題應該有助於澄清你:什麼是C++指針變量和引用變量之間的區別是什麼? (http://stackoverflow.com/questions/57483/what-are-the-differences-between-pointer-variable-and-reference-variable-in-c) – yasouser

+0

這類似於(到http://stackoverflow.com /問題/ 18426473 /預增 - 不工作,AS-I-期望/ 18426505#18426505)。 你缺少一個序列點。 –

回答

6

關於重定向操作符<<的一個令人討厭的事情是,它們直觀地傳達了確實不存在的「順序計算」的缺陷。

當你寫

std::cout << f() << g() << std::endl; 

輸出將首先顯示的f()結果,然後g()的結果,而是g()實際調用可以調用f()之前發生。

它甚至會比這更糟糕......這不是該序列是不可預測的,但確實序列的概念本身是無效的。在

std::cout << f(g()) << h(i()) << std::endl; 

它例如法律的第一個函數被調用爲g(),其次爲i(),其次是h()最後由f()。甚至不保證所有調用的順序都是相同的(不是因爲編譯器製造商喜歡嘲笑你,而是因爲代碼可以內聯,並且如果包含函數在不同的上下文中內聯,編譯器可以決定不同的順序)。

唯一C++運算符,在所述評價順序保證的序列是:

  1. &&:首先評估左側且僅當結果爲「真」的計算結果的右側
  2. ||:首先評估只有在結果爲「假」時評估右側
  3. ?::首先評估條件,然後僅評估第二或第三個操作數
  4. ,:逗號運算符...評估左側,丟棄該值,然後評估並返回右側。注:函數參數之間的逗號不是逗號運算符,也不會執行評估命令。

而且這guaratee只針對預定義的運算符有效。如果您的班級中存在&&||,,他們只是普通的操作員,對評估順序沒有任何特殊限制。

任何其他運營商不徵收評估順序任何限制,這包括<<即便利用某種技巧,你以爲。

19

計算表達式爲:

((cout << x) << " ") << --y; 

有左手側的評估和表達式的右手側時,編譯器可以輸出代碼之間沒有序列點(或排序)作爲第一步評估--y

由於yx這裏的參考,這是因爲你無論從閱讀和中間沒有順序點在同一個表達式寫入x實際上未定義的行爲。

+0

請檢查編輯的代碼這肯定與指針算術有關。當我們說y有一個地址x即80,並嘗試和減少y時,它也不會在我的系統上遞減。 –

+4

@SanyamGoel:這是未定義的行爲。不同的編譯器可以(也將會)輸出不同的東西。 LHS和RHS的評估順序是實現定義的,加上對'x'的讀取和寫入,沒有順序點=>未定義的行爲(即它不是合適的C++,它可以做任何事情)。 – Mat

+0

建議編輯:*「請參閱[本SO線程](http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points)的詳細解釋。「* – jrok

1

這是未定義的行爲,C/C++標準沒有定義該參數的方式被壓入堆棧,和通常的說法是按相反的順序這裏推動時,例如:

func(1, 2) 

將被評估喜歡的東西:

push 2 
push 1 
call func 

所以你的情況,--y進行評估,並推動x不前。正是在這個例子清楚:

#include <iostream> 

int a() { std::cout << "a" << std::endl ; return 1; } 
int b() { std::cout << "b" << std::endl ; return 2; } 

int main(void) { 

    std::cout << a() << " " << b() << std::endl; 

    return 0; 
} 
從第一次看

,它應該打印:

a 
b 
1 2 

但它打印:

b 
a 
1 2 
0
x++ 

增量X併產生作爲表達式的結果是x的原始值。

特別是,對於x ++,沒有時間順序暗示增加和產生x的原始值。編譯器可以自由發出產生x的原始值的機器碼,例如,它可能出現在某個寄存器中,並且延遲增量直到表達式結束(下一個序列點)。雖然x++似乎增加x到,它不會直到打印。根據--y,它將獲得增加的值(81)並在打印之前將其減少,因爲它是前綴運算符。