3

チェインされた静的関数とメンバー関数で引数の評価順序に違いがあるのはなぜでしょうか。この質問の回答から、このような連鎖関数呼び出し間の引数評価順序が指定されていないことがわかります。たとえば、次のスニペットを見てください。

#include <iostream>
class test {
public:
    static test& chain_s(test& t, int i) {
        std::cout << i << " ";
        return t;
    }

    test& chain(test& t, int i) {
        std::cout << i << " ";
        return *this;
    }
};

int main(int, char**) {
    int x = 2;
    test t;
    t.chain(t,++x).chain(t,++x).chain(t,++x);
    x = 2; std::cout << std::endl;
    t.chain_s(t,++x).chain_s(t,++x).chain_s(t,++x);

    return 0;
}

GCC 4.6.2 および CL 15.00.30729.01 (MSVC 9) の場合、結果の出力は私のためのものです

5 5 5
3 4 5

しかし、仕様に何らかの理由があるのか​​ 、それとも静的関数が左から右に(引数とともに)評価され、非静的関数の場合はすべての引数が最初に評価されるのか(right-私が他のテストで見たものから左へ)。

私がこれを尋ねている理由は、C で (構造体と関数ポインターを使用して) 同様の動作を取得しようとして失敗したときに、この動作の違いに最初に気付いたからです。これは、メンバー関数の GCC と MSVC の両方で実装された最適化であると強く疑っていますが、ここの誰かがこれについてもう少し詳しく説明してくれることを願っています。

編集:
奇妙に感じる重要な情報を 1 つ言及するのを忘れていました: GCC は、チェーンされた非静的関数の未指定の動作についてのみ警告しますが、静的関数については警告しません:

a.cpp: In function 'int main(int, char**)':
a.cpp:18:45: warning: operation on 'x' may be undefined [-Wsequence-point]

GCC はそのような警告を提供する義務はないので、2 番目の式を見逃す可能性がありますが、これが何か興味深いことが起こっていると私に思わせます。

4

2 に答える 2

2

理由はありません。あなたが言うように、順序は言語によって指定されていません。

右から左の順序を使用する理由の 1 つは、 のような可変数のパラメーターを持つ関数ではprintf、常に最初のパラメーターが一番上になるためです。そうでなければ、それは問題ではありません。

于 2012-01-17T19:27:38.817 に答える
2

あなたのコードには未定義の動作がありますが、あなたはそれを知っていると思います. また、最適化フラグに応じて違いを簡単に確認できます。ただし、この場合、考えられる理由の 1 つは、非静的関数が前の呼び出しの結果を含む 3 つの引数を必要とすることです。一方、静的関数は 2 つしか必要とせず、前の呼び出しの結果は無視されます。

于 2012-01-17T20:07:12.987 に答える