三項演算子/条件演算​​子内に増分/減分演算子を配置しても安全ですか? 質問する

三項演算子/条件演算​​子内に増分/減分演算子を配置しても安全ですか? 質問する

例を挙げてみましょう

#include <iostream>
using namespace std;
int main()
{   
    int x = 0;
    cout << (x == 0 ? x++ : x) << endl; //operator in branch
    cout << "x=" << x << endl;
    cout << (x == 1 || --x == 0 ? 1 : 2) << endl; //operator in condition
    cout << "x=" << x << endl;
    return 0;
}

出力:

0
x=1
1
x=1

出力は理解できますが、これは未定義の動作でしょうか?どちらの場合でも評価の順序は保証されますか?

たとえ保証されていたとしても、増分/減分を使用するとすぐに読みやすさの問題が発生する可能性があることはよくわかっています。次のような増分/減分演算子のあいまい/未定義の使用例がたくさんあることを考えると、同様のコードを見てすぐに確信が持てなかったため、質問しただけです...

  • C++ では、関数パラメータが評価される順序は定義されません。

    int nValue = Add(x, ++x);
    
  • C++ 言語では、シーケンス ポイント間で変数を複数回変更することはできません。

     x = ++y + y++
    
  • インクリメント演算子とデクリメント演算子には副作用があるため、プリプロセッサ マクロでインクリメント演算子またはデクリメント演算子を含む式を使用すると、望ましくない結果が生じる可能性があります。

     #define max(a,b) ((a)<(b))?(b):(a)
     k = max( ++i, j );
    

ベストアンサー1

条件演算子の場合(§5.16 [expr.cond]/p1):

最初の式に関連付けられたすべての値の計算と副作用は、2 番目または 3 番目の式に関連付けられたすべての値の計算と副作用の前に順序付けられます。

論理OR演算子の場合(§5.15 [expr.log.or]/p1-2):

最初のオペランドが と評価された場合、2 番目のオペランドは評価されませんtrue。 [...] 2 番目の式が評価された場合、最初の式に関連付けられたすべての値の計算と副作用は、2 番目の式に関連付けられたすべての値の計算と副作用の前に順序付けられます。

コードの動作は明確に定義されています。

おすすめ記事