运算符中的执行顺序<<

时间:2013-02-11 10:11:06

标签: c++ stream operator-keyword cout ostream

我很难理解下面代码中的调用顺序。 我期待看到下面的输出

    A1B2

虽然我可以看到我得到的输出是

    BA12

我认为通话std::cout<< b->fooA() << b->fooB() << std::endl等同于通话

  std::cout.operator<<( b->fooA() ).operator<< ( b->fooB() )

但我可以看到情况并非如此。你能帮助我更好地理解它是如何运作的以及与全球operator<<的关系吗?这最后一次是按照这个顺序调用的吗?

此致

AFAG

    #include <iostream>

    struct cbase{
        int fooA(){
            std::cout<<"A";
            return 1;
        }
        int fooB(){
            std::cout <<"B";
            return 2;
        }
    };

    void printcbase(cbase* b ){
        std::cout << b->fooA() << b->fooB() << std::endl;
    }

    int main(){
        cbase b;
        printcbase( &b );
    }

3 个答案:

答案 0 :(得分:9)

编译器可以将函数printcbase()评估为:

void printcbase(cbase* b ){
    int a = b->FooA();    // line 1
    int b = b->FooB();    // line 2
    std::cout << a;       // line 3
    std::cout << b;       // line 4
    stc::cout << std::endl;
}

或标记为1 - 4的许多线条的一些。只保证第1行在第3行之前完成,第2行在第4行之前完成(当然第4行在第4行之前)。标准没有说更多,实际上你可以期望使用不同的C ++编译器得到不同的结果。

答案 1 :(得分:5)

<<的执行顺序已明确定义,但子表达式的评估顺序未在C ++中定义。 This article and the C code example说明了您提到的问题。

BA12AB12都是正确的。在以下代码中:

std::cout<< b->fooA() << b->fooB()

1将出现在2之前,但A可能出现在B之前或之后,因为编译器未承诺是否会评估{首先{1}}或fooA

答案 2 :(得分:2)

移位运算符是左关联的; a << b << c读为(a << b) << c,这意味着如果a属于具有成员用户定义的operator<<的类型(并返回该类型),那么表达式将显示为{{1} }}。如果使用免费的a.operator<<(b).operator<<(c),则会将其显示为operator<<

因此,在评估operator<<(operator<<(a, b), c)之前对a << b的评估进行了排序,但(a << b) << cb的评估之间没有排序依赖关系:

c

如果我们对副作用进行编号,那么副作用可以按以下任何一种顺序排列:

a << b << c[1]
|         |
a << b[2] |
|    |    c[5]
a[3] b[4]