2016-11-27 167 views
3

我試圖弄清楚C++ 11規範中是否有任何東西。以下代碼預期的行爲(GitHub link here):C++評估順序

struct Scalar { 
    int data; 

    Scalar(int x) : data(x) {} 

    int get() { 
     return data; 
    } 

    Scalar &square() { 
     scale(data); 
     return *this; 
    } 

    void scale(int rhs) { 
     data *= rhs; 
    } 
}; 

int main() { 
    Scalar v(3); 

    v.square().scale(v.get()); 

    return v.data; 
} 

這主要是來自因爲發現這樣做g++clang++之間不同的東西組成:

$ g++ --version 
g++ (GCC) 6.2.1 20160830 
Copyright (C) 2016 Free Software Foundation, Inc. 
This is free software; see the source for copying conditions. There is NO 
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 

$ clang++ --version 
clang version 3.9.0 (tags/RELEASE_390/final) 
Target: x86_64-unknown-linux-gnu 
Thread model: posix 
InstalledDir: /usr/bin 

$ g++ -std=c++11 order_of_ops.cpp -o a.out && ./a.out; echo $? 
27 

$ clang++ -std=c++11 order_of_ops.cpp -o a.out && ./a.out; echo $? 
81 

答案似乎應該是的第5.2.2節和第5.2.5節,但我無法追查具體的東西。

+1

'方()'和'得到()'必須調用'規模之前調用()'。但是它們之間的相對順序並沒有被標準所指定。 – StoryTeller

+1

我不會夢想嘗試這樣的事情。未定義的行爲。 –

+0

當你想要的東西具體的呈現給您所TA'ing學生,這些都是你問(題型: – Pockets

回答

8

如果我正確地閱讀東西,您的代碼的行爲是未指定的。 N3337爲C++ 11個引號:

§1.9 [intro.execution]/15

除非另有說明,個體經營者 的操作數的和個別表達式子表達式的評估是未測序。 [...] 如果標量對象上的副作用是相對於任一 同一標量對象在另一側的效果或使用相同的標量對象的值的值計算 未測序,該行爲是未定義的。那是不是另有具體測序之前或 之後被調用的函數體的執行是不定

它遵循調用函數中的每個評估(包括其他功能 調用) 關於執行被叫 函數進行排序。 9)換句話說,函數執行不會與其他每個 交錯。

§5.2.2 [expr.call]/8

[注:後綴表達式和 參數表達式的評估都是相對於未測序另一個。所有 參數表達式評估的副作用在輸入函數 之前被排序(參見1.9)。 末端注]

所以,你的修改和Scalar::data無關讀的不定測序。

這就是說,它很可能會改變,並在C++ 1Z良好定義:

N4606§5.2.2 [EXPR。調用]/5

在 表達式列表中的每個表達和任何默認參數前後綴表達式進行測序。一個 參數,包括每個關聯值的計算和側 效果的初始化,是不定相對於任何其他 參數的測序。

因此,在C++ 1Z您v.data應該等於81(如果我讀正確的事情)

+2

預C++ 11,當我們談到序列點,有一個序列點之前和每個函數調用後。這將使明確的表達,而是用一個未指定的結果取決於調用的順序。 –

+0

@TC如何函數參數(S)和後綴表達式的這個有關?評估指定被叫函數在執行函數體之前都被排序,但是它們之間並沒有相對的排列順序 – krzaq

+1

啊,等等,我用c/p'd錯誤的引號,我的意思是「在調用函數中的每個評估(包括其他函數調用)在被調用函數的主體的執行之前或之後未被特別排序的情況相對於調用的執行被不確定地排序d函數「。現在考慮在該語句中有三個函數調用。 –