4 回答

TA貢獻883條經驗 獲得超454個贊
其實這兩種結果都有可能出現。
先明確一下關于運算符和操作數的基本知識:運算符需要有操作數才能構成表達式(比如 a + b 就是一個加法表達式,+ 是運算符,a 和 b 就是操作數)。而運算符表達式在執行時有一個“操作數求值”的過程(也就是確定 a 和 b 的值)。
如果操作數本身是個函數調用,那么對這個操作數求值就是得到函數的返回值。有一點很重要:函數中的一些代碼(尤其是 cout << 這樣的IO操作)的行為算是函數的副作用,這些副作用的發生并不一定和求值同時發生。
關于表達式的副作用何時發生,C++ 其實有比較復雜的序列點規則。我不打算細說這個規則,后面遇到具體情況時我會提到它,你目前只需要記住副作用不一定和求值同時發生。
那么我用你的這個例子具體說明一下:
cout<<x.f1()<<x.f2() 這是一個復合表達式。
對其中的?cout << x.f1() 這個子表達式來說?x.f1() 是右操作數,這個右操作數是個函數調用。
而 << 其實也是函數調用,這是重載 << 運算符函數。x.f1() 其實算是 << 函數的參數。
cout<<x.f1()<<x.f2() 其實是連續兩次 << 調用,并且是?<<x.f1() 在前,<<x.f2() 在后(運算符的優先級決定的)。也就是說一定是先調用了 << 5,再調用 << 3,所以最后結果是 53(5在3之前)。
至于讓你疑惑的那部份輸出:C++ 的求值和序列點規則說“參數的副作用要在函數執行前發生”。注意:只是在之前發生即可。
所以完全有可能 f1() 和 f2() 的副作用(也就是輸出"f1: m = 5"和"f2: m = 3")在兩次 << 函數調用前就已經發生了。加之 C++ 沒有規定參數副作用誰先誰后,所以"f2: m = 3"先輸出是有可能的。
====以上就是關于你看到的這個結果的解釋====
下面我想多說下:
我不知道你用的編譯環境是什么? 編譯器遵循的是哪個標準?
實際上如果你用的編譯器支持的 C++ 標準夠新的話(C++17),f1: m = 5 和 5 是會先輸出的。
這是因為在 C++17 標準中增加了一些序列點規則,導致這個代碼的行為不再是不確定的,而是保證會先輸出?f1: m = 5 和 5。
(我有些好奇不同編譯器在各個標準下的行為,希望能告知我你用的編譯環境是什么)
最后,你知道你其實根本就沒用到 X 的成員變量 m 吧...
- 4 回答
- 1 關注
- 1802 瀏覽
添加回答
舉報