2

gcc の奇妙な動作を指摘しました。同じ変数が同じ命令で使用され、この変数が 1 つの関数呼び出し (参照またはポインターによって渡された変数) によって変更された場合、変数の変更は他の関数の変更されません。同じ指示。

それは通常の C++ の動作ですか、それとも偽物ですか?
注: 最適化 (-O) フラグは設定されていません。
注 2: これは、solaris CC コンパイラで問題なく動作します。

gcc 4.5.3 を使用したデモ (Linux または mingw/cygwin 上)

class C {
public:
  const C & inc(int & i) const       
  {
     ++i;
     cout << "inc: i = " << i << endl; return *this;
  }
  const C & see(int i) const   
  {     
     cout << "see: i = " << i << endl; return *this; 
  }
  const C & see2(const int & i) const {  
    cout << "see2: i = " << i << endl; return *this; }
  };

int main()
{
  C c;
  int i = 0;
  c.see(i).inc(i).see(i).see2(i).inc(i).see(i).see2(i);
  c.see(i);
  return 0;
}

出力:

see: i = 0
inc: i = 1
see: i = 0 : 1 予想
see2: i = 1
inc: i = 2
see: i = 0 : 2 予想
see2: i = 2
see: i = 2

4

2 に答える 2

2

関数の引数の評価順序は、相互に不定です。この場合、gcc は早期にメソッド呼び出しiに渡されるように評価することを選択しました。see

あなたのコードは以下と同等です:

class C {};
C &inc(C &c, int &i) { ++i; return c; }
C &see(C &c, int i) { std::cout << i << '\n'; return c; }
C c;
int i = 0;
see(inc(c, i), i);

の引数の有効な評価順序は次のseeとおりです。

1. evaluate inc(...) to pass c to see(...)
2. evaluate i as an rvalue to pass to see(...)

1. evaluate i as an rvalue to pass to see(...)
2. evaluate inc(...) to pass c to see(...)

前者の場合、プログラムは1;を出力します。後者では、それは印刷され0ます。

動作は未規定ですが未定義ではないことに注意してください。またはのいずれかを出力する必要があり0ます1。これは、シーケンス ポイントが への呼び出しの前後に取得されるためincです。C++11 では、関数の実行は、呼び出し元の関数 (1.9p15) での評価に関して、不定に順序付けられます (順序付けされていないわけではありません)。

于 2012-11-29T12:37:23.973 に答える
0

これは正しい動作です。指定されたステートメントの部分式が実行される順序は、標準では指定されていません。あなたの場合、明らかにコンパイラは最初にすべてのi部分式を実行します。つまり、 のコピーを作成て の異なる呼び出しにi渡し、 への呼び出しが評価されます。see()inc()

于 2012-11-29T12:39:59.873 に答える