How to determine C++ function call order?

后端 未结 3 1408
予麋鹿
予麋鹿 2021-01-23 05:11

I\'ll skip the headers

class X {
    int i;
    static int j;

public:
    X(int ii = 1) : i(ii) {
        j = i;
    }
    static int incr() {
        return ++         


        
相关标签:
3条回答
  • 2021-01-23 05:37

    § 1.9.13

    Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread (1.10), which induces a partial order among those evaluations. Given any two evaluations A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced. [ Note: The execution of unsequenced evaluations can overlap. —end note ] Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which. [ Note: Indeterminately sequenced evaluations cannot overlap, but either could be executed first. —end note ]

    In other words, the order the functions are called is Undefined. That doesn't mean "we don't know", it doesn't mean "you can't work it out" - it means that it is defined as having no definition; the compiler and cpu are free to complete them in any order.

    Consider the following:

    int a[3];
    
    void f1() { a[0] = 1; }
    void f2() { a[1] = 2; }
    void f3() { a[2] = 3; }
    
    int main() {
        f1(), f2(), f3();
    }
    

    Basically the language asserts no requirement for ordering on a statement like

    std::cout << f1() << f2() << f3();
    

    Your code has no sequence points (http://en.wikipedia.org/wiki/Sequence_point) between the function calls; you could figure out the order your compiler generates, but it might behave differently on a different CPU or a different optimization level.

    If you have mutable function calls like that, you'll need to manually hoist or add breaks:

    std::cout << f1();
    std::cout << f2();
    std::cout << f3();
    

    or

    auto a1 = f1();
    auto a2 = f2();
    auto a3 = f3();
    std::cout << a1 << a2 << a3;
    
    0 讨论(0)
  • 2021-01-23 05:37

    This statement

    cout << x.f() << xp->f() << X::f();
    

    can be rewritten like

    cout.operator <<( x.f() ).operator <<( xp->f() ).operator <<( X::f() );
    

    The order of evaluations of expressions used as arguments in this statement is unspecified. So the compiler can evaluates them for example from left to right or from right to left. Thus using different compilers you can get different results.:)

    To get a deterministic result you should rewrite statement

    cout << x.f() << xp->f() << X::f();
    

    for example like

    cout << x.f();
    cout << xp->f();
    coit << X::f();
    
    0 讨论(0)
  • 2021-01-23 05:43

    The stream operator is simply an operator. C++ allows operators to be defined a multitude of ways. What you're seeing is the << operator for strings. What you're doing is the same thing as:

    cout << "word1" << "word2" << "word3";
    

    The expect output for that is:

    "word1word2word3"
    

    However, the evaluation order is determined by the implementation of the << operator. Usually the above is equivalent to:

       (((cout << "word1") << "word2") << "word3");
    

    Replace the strings with functions instead and you see the first one evaluated is actually "word3". This is not strictly the case, just what you'll usually see.

       (((cout << func1()) << func2()) << func3());
    

    Evaluation order would be func3, func2, func1, with print order the return of func1, func2, func3.

    0 讨论(0)
提交回复
热议问题