2013-06-06 71 views
2

我正在學習C++,最近碰到一個令人困惑的問題中的函數調用,下面的代碼:C++的cout語句

#include <iostream> 

using namespace std; 

class A { 
    public: 
     A() { a[0] = 1; a[1] = 0; } 
     int a[2]; 
     int b(void) { int x=a[0];a[0]=a[1];a[1]=x; return x; } 
}; 

int main(void) { 
    A a; 
    cout<<a.a[0]<<a.a[1]<<endl; //outputs 10 
    a.b(); 
    cout<<a.a[0]<<a.a[1]<<endl; //outputs 01 
    a.b(); 
    cout<<a.a[0]<<a.a[1]<<endl; //outputs 10 

    cout << a.b() << //outputs 1 
    endl<< a.a[0]<<a.a[1] << endl; //outputs 10??? 

    cout<<a.a[0]<<a.a[1]<<endl; //outputs 01??? 
    return 0; 
} 

前兩個B的()的調用行爲與預期相同,但是當我打電話b()在cout語句中,它不會馬上切換數組的兩個元素,但後來我檢查它,它已經被切換了。

你能幫助我理解這種行爲?謝謝。

+1

請允許我建議你那是這個問題(和許多類似的)的副本:http://stackoverflow.com/questions/10782863/what-is-the-correct-answer-for-cout-cc – jogojapan

+0

@jogojapan - 它不是這個問題的重複,因爲有一個函數調用引入了一個序列點。 –

+0

@PeteBecker正如你在你的回答中所說的那樣,這兩個評價是無序的(相對於彼此)。由於其中一個對另一個讀取的左值具有副作用,所以與重複問題中描述的基本情況相同。 – jogojapan

回答

4

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

兩個功能的評價的該命令的調用是未指定的;編譯器可以調用g()然後f(),或者它可以調用f()然後g()

在你的代碼

同樣的事情;編譯器可以松鼠遠的a.a[0]值調用a.b(),或者它可以調用a.b()然後抓住的a.a[0]值。

+0

不幸的是,對方的回答已經被刪除,但我在那裏發表你的評論:爲什麼它實際上是未定義的行爲,其原因之一是兩個評估之一對另一個評估正在閱讀的左值有副作用。該標準說,這種情況必須始終被視爲未定義的行爲。 – jogojapan

+0

@jogojapan - 請參考? –

+0

C++ 11在1.9/15中使用它:_If對於標量對象的副作用不是相對於同一個標量對象的其他影響或使用相同標量對象的值進行值計算而言,這種行爲是未定義的。在C + + 03中它有點複雜,看到這個答案:http://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points – jogojapan