2016-11-27 11 views
3

私はC++ 11の仕様に何かがあるかどうかを判断しようとしています。次のコード(GitHub link here)のために期待される動作:それはであるべきのように答えがC++評価の順

$ 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 

ようだ:

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++の間で異なるものをないことを発見のほとんどがアップしますの§5.2.2と§5.2.5しかし、私は具体的な何かを追跡するのに問題があります。

+1

'四角() '(私が正しく物事を読んでいる場合)と'規模 'の呼び出しの前に呼び出されなければならない81と同じでなければなりません() 'を返します。しかし、それらの間の相対的な順序は、規格によって特定されていません。 – StoryTeller

+1

私はこのようなことを試すことを夢見ることはありません。定義されていない振る舞い。 –

+0

あなたがTAをしている生徒に具体的なものを提示したいときは、これが質問の種類です( – Pockets

答えて

8

私が正しく読むと、コードの動作は不明です。 C++ 11の符用N3337:

§1.9 [intro.execution]/15記載した以外

は、個々のオペレータ のオペランドの、個々の表現の部分式の評価はunsequencedあります。 [...] 同じスカラーオブジェクトの別の副作用 または同じスカラーオブジェクトの値を使用する値計算 のいずれかに対してスカラーオブジェクトの副作用が順序付けされていない場合、その動作は未定義です。

が、それは

で呼び出される関数の本体の実行が不確定である前または後 他に具体的に配列決定されていません(他の機能 呼び出しを含む)呼び出し関数内のすべての評価を以下の は、呼び出された 関数の実行に関してシーケンスされます。

9)つまり、関数実行は、それぞれ その他とインターリーブしません。

§5.2.2 [expr.call]/8

[注:後置式のと 引数式の評価は全てのunsequenced相対的お互いに。すべての 引数の評価の副作用は、 関数が入力される前に順序付けられます(1.9参照)。だから、末端ノート]

は、あなたの修正とScalar::dataの無関係な読み取りが不定に配列決定されます。言われ、変更とC++ 1Zにおいてよく定義される可能性があること

N4606§5.2.2 [式expr。呼び出し]/5

後置式は 表現リスト内の各表現および任意のデフォルト引数の前に配列決定されます。パラメータの初期化(関連するすべての値の計算と側面 の効果を含む)は、他の パラメータのそれに対して不確定に配列されます。

したがって、C++で1Zごv.data()を取得 `

+2

Pre-C++ 11、シーケンスポイントについて話したときにシーケンスがありました各関数呼び出しの前と後にポイントを指定すると、式が正しく定義されますが、呼び出しの順序によって結果が不明になります –

+0

@TCこれはどのように関連していますか?関数の引数と呼び出し後の式を評価する関数は、関数本体の実行前に順序付けされていますが、互いに順序付けされていません。 – krzaq

+1

ああ、私は間違った見積もりをしました。呼び出された関数の本体の実行前または実行後に特別に順序付けされていない呼び出しは、呼び出しの実行に関して不確定に順序付けられますd関数を呼び出すことができます。このステートメントには3つの関数呼び出しがあるとします。 –