2012-02-10 39 views
2

可能重複:
How do we explain the result of the expression (++x)+(++x)+(++x)?
Undefined Behavior and Sequence PointsC + C++ =未定義的行爲?

我有問題,在不同方式的代碼

U = C + C++; 

會運行非標準類型和我自己的類型。 我舉一個例子http://ideone.com/4S1uA其中我有不同的int值和我的類Int值,它應該代表真正的Int工作方式。

是否有可能使我的類的行爲方式與標準int的工作方式相同?此代碼是否有未定義的行爲?

爲什麼它是非玩家的行爲? C++有一個操作優先級,所以c++應該先評估,因爲它會改變a的值,所以爲了增加第一個參數應該傳遞新值a並作爲第二個舊值。它對Int類是這樣工作的,但對於standart int不適用。

+5

是的,這是未定義的行爲。我會讓其他人創建一個答案,引用標準等。 – 2012-02-10 20:45:01

+1

請參閱http://stackoverflow.com/questions/367633/what-are-all-the-common-undefined-behaviour-that-ac-programmer -should-know-ab – Dervall 2012-02-10 20:46:22

+1

是的,它是UB,因爲它是未定義的,否則將首先評估「C」或「C++」。 – 2012-02-10 20:46:56

回答

4

此代碼未定義的行爲?

是的。關於副作用,操作數的評估順序是未定義的。

第6.5節(2)的標準的說:

如果一個標量對象上的副作用是相對於相同的標量對象上或者是不同的副作用或一個值計算未測序使用的值同一個標量爲 的對象,其行爲是未定義的。如果子表達式的子表達式存在多個允許的排序順序,則如果在任何排序中出現這種不確定的方面效應,則行爲是不確定的。

由於int是一個標量類型,並且由於此處的副作用是未定義的,因此行爲未定義。

你應該寫你這樣的代碼:

U = 2*C; 
C++; 
+0

我無法想象需要構建'c + C++'時的情況,但是我對這個代碼應該如何工作有一些爭論。但是C++有一個操作優先級,所以應該首先評估C++,因爲它改變了a的值,所以爲了增加,第一個參數應該是新值的改變,而第二個是舊值。但是這對於構建類型不起作用。 – Seagull 2012-02-10 20:53:23

+2

操作數評估的順序未定義。 – 2012-02-10 20:56:01

+3

@海鷗:這不是運營商優先的問題。是的,++操作在+操作之前發生(由於優先級),但不會告訴您何時在該操作的左側評估C的值。 – 2012-02-10 20:58:21

2

是的,這是不確定的行爲。在語句中也不能訪問變量兩次,該語句也會修改它,因爲未定義表達式「C」和表達式「C++」的求值順序。

2

這裏涉及的概念是sequence points之一。

在命令式編程的序列點定義了它保證了先前評估的所有副作用將被執行的計算機程序的執行任意點,無副作用:從維基百科的文章引用開頭一句來自後續評估的效果尚未完成。

在C中,操作者+確實創建序列點。因此副作用的順序沒有定義。但是,在C++中,重載的operator +是一個函數調用,它確實創建了一個序列點。這會在副作用方面產生不同的行爲。請注意,雖然未指定評估函數參數的順序,但在函數進入之前所有副作用都已完成。因此,如果C + C++涉及過載的+運算符,則在執行+函數之前+的左邊參數將應用於函數。這與int值的情況不同,其中在完成右側的副作用之前可以評估或不評估左側。

+0

'如果C + C++涉及一個重載的+運算符,那麼在+函數執行之前,C++副作用將應用於+的左參數。否,'f(c,C++)'對於標量c也是UB。 – Cubbi 2012-02-10 21:14:25

+0

@Cubbi - 我沒有說這種行爲是必然定義的。我說在'+'執行之前'++'的副作用已經完成了(不像內建的'+'運算符,它不會創建一個序列點)。對於標量,顯然參數評估(UB)的順序決定了傳遞給函數的值。對於對象來說,問題的關鍵是''看作左邊的參數,保證包含'++'的效果。 – 2012-02-12 19:00:34