25

このコード例を見てください:

int a = 10;
int b = 20;
int c = 30;

int & foo1() {
    qDebug() << "foo1" << endl;
    return a;
}

int & foo2() {
    qDebug() << "foo2" << endl;
    return b;
}

int & foo3() {
    qDebug() << "foo3" << endl;
    return c;
}

int main(void)
{
    foo1() = foo2() = foo3() = 7;
}

割り当ては右から左に進むので、foo3最初とfoo1最後を見ると思っていましたが、逆です。

そのようなシナリオのルールは具体的にどのように定義されていますか? また、コンパイラは割り当てと他の演算子を=区別しますか?初期化とは異なるコンテキストで演算子を使用している場合、それはどのように可能でしょうか? チェーン割り当ては、他のチェーンとは異なる方法で処理されるのでしょうか?

4

3 に答える 3

24

完全な表現

foo1() = foo2() = foo3() = 7

次のツリーで抽象化できます。

     =
   /   \
foo1()   = 
       /   \
    foo2()   =
           /   \
        foo3()   7

そのツリーの葉は任意の順序で評価できます。コンパイラは自由に選択できます。代入演算子を呼び出す場合にのみ、それらにぶら下がっている式を最初に評価する必要があります。あなたの場合、葉は、次にの順foo1()に評価されます。foo2()foo3()

の右から左への結合性=は、ツリーの形状にのみ見られ、評価の順序には見られません。のためのツリー

std::cout << foo1() << foo2() << foo3()

のように見える

                   << 
                 /    \
              <<      foo3()
            /    \
         <<      foo2()
       /    \
std::cout   foo1()

ここでも、foo関数は任意の順序で評価できますが、 の評価順序はoperator<<()明確に定義されています。トピックを非常によく説明しているシーケンス ポイントに関する興味深い投稿があります。

于 2013-06-24T14:58:48.510 に答える
15

演算子の結合性 (つまり、右から左) は評価順序とは関係ありません。* オペランドの評価順序は規定されていません。


* いくつかの場合を除いて、すなわち&&||および,.

于 2013-06-24T14:48:16.383 に答える
2

部分式が評価される順序は、結果が適用される順序と同じではありません!

foo1() は早期に呼び出すことができますが、他のものも完了する前に割り当て自体を適用してはなりません。

于 2013-06-24T14:49:54.063 に答える