0

この質問と回答から - cout << c++ << c; の正解は何ですか?

わかりました

std::cout<<c++<<c;

は次のように評価されます。

std::operator<<(std::operator<<(std::cout, c++), c);

したがって、未定義の動作は、2 つのパラメーターのいずれかが最初に評価される可能性があるという事実から生じます。ここまでは順調ですね。

しかし、なぜstd::operator <<ですか?なぜstd::ostream::operator <<呼び出されないのですか?もしそうなら、それは次のように翻訳されませんか

(ofstream::operator<<(c++)) << c;
              |
     returns ofstream&

これとメソッドチェーンの違いは何ですか:

struct A
{
    A& foo();
    void goo();
};
//...
A a;
a.foo().goo();

?

4

1 に答える 1

3

std::ostreamオーバーロードされたメンバー演算子として提供しますoperator<<が、他のヘッダー ( など<string>) は自由な演算子を提供します。したがって<<、メンバー演算子かフリー関数かは、RHS の型によって異なります。

ただし、どちらでもかまいません。<<asfoocoutasの名前を変更しましょうbar:

foo(foo(bar, c++), c);
bar.foo(c++).foo(c);

どちらの場合もfoo、特定の順序で呼び出す引数を評価する実装上の要件がないため、動作は未定義です。重要な考慮事項は、Annex C に従って、チェーンされたメソッド呼び出しが複数の完全な式を構成しないことです。コンパイラが見た場合

foo.bar(<some-complex-expression>).baz(<another-complex-expression>);

bartoとto の引数に CSE と並べ替えを自由に適用できますbaz。実際、副作用を調べると、 への引数が への引数のbaz前に評価されることがわかる場合がありますbar

struct A { A &foo(int) { return *this; } };
#include <cstdio>
int main() { A().foo(printf("hello\n")).foo(printf("bye\n")); }

私のコンパイラ (gcc 4.1.2) は、出力するプログラムを生成しますbye\nhello\n

于 2012-06-29T12:47:43.263 に答える