11

次のコードを想定します。

#include <iostream>
using namespace std;

char one()
{
    cout << "one\n";
    return '1';
}

char two()
{
    cout << "two\n";
    return '2';
}

int main(int,char**)
{
    // 1:
    cout << one()
         << '\n'
         << two()
         << '\n';

    // 2:
    operator<<(
        operator<<(
            operator<<(
                operator<<(
                    cout, 
                    one()),
                '\n'),
            two()),
        '\n');
}

1およびとしてマークされた行を実行2し、ideone でコンパイルすると同じことが行われ、次のように出力されます。

two
one
1
2

私の見解では、関数の引数が解決される順序が指定されていないため、ここで観察される動作は指定されていません。

これはインタビューでの質問で、上記のシーケンス (代替なし) を印刷するのが正解のはずでしたが、本当に正しいのでしょうか?

4

2 に答える 2

13

あなたの言うとおりです。インタビュアーは、言語とその規則について驚くほど一般的な理解不足を示しています。

operator<<これらの 2 行は、最初の行で呼び出されるすべての関数が常にフリー関数である場合に限り、厳密に同等です (標準ではフリー関数であると規定されています)。

あなたが正しく考えたように、関数呼び出し間の順序付けは、1 つの引数が別の引数の戻り値である場合を除き、不定に順序付けられます (前か後か、どちらが指定されていないか):

1.9 プログラムの実行[intro.execution]

[...]
15 [...]
関数を呼び出すとき (関数がインラインであるかどうかにかかわらず)、すべての値の計算と引数式、または呼び出された関数を指定する後置式に関連付けられた副作用は、前に配列されます。呼び出された関数の本体にあるすべての式またはステートメントの実行。[ 注: 異なる引数式に関連付けられた値の計算と副作用は順序付けされていません。--end note ]呼び出された関数の本体の実行の前後に特に順序付けされていない、呼び出し側関数 (他の関数呼び出しを含む) 内のすべての評価は、不定に順序付けられます。9 C++ のいくつかのコンテキストでは、対応する関数呼び出し構文が変換単位に現れなくても、関数呼び出しの評価が行われます。[ 例: 新しい式の評価は、1 つ以上の割り当て関数とコンストラクター関数を呼び出します。5.3.4 を参照してください。別の例として、変換関数 (12.3.2) の呼び出しは、関数呼び出し構文が表示されないコンテキストで発生する可能性があります。—end example ]呼び出された関数の実行に関するシーケンス制約 (上記のとおり) は、関数を呼び出す式の構文が何であれ、評価される関数呼び出しの機能です。

すべてのパーツに名前を付ける:

cout << one() // a) execute one()           ("one\n")
              // b) output the return-value ("1")
     << '\n'  // c) output newline          ("\n")
     << two() // d) execute two()           ("two\n")
              // e) output the return-value ("2")
     << '\n'; // f) output newline          ("\n")

順序付けの制約:

a < b < c < e < f
d < e < f

または別の表現:

a < b < c <
          < e < f
d         <

したがって、すべての有効なフルオーダー:

abcdef "one\n1\ntwo\n2\n"
abdcef "one\n1two\n\n2\n"
adbcef "one\ntwo\n1\n2\n"
dabcef "two\none\n1\n2\n"
于 2014-08-23T21:19:05.250 に答える