Order of evaluation of arguments using std::cout

前端 未结 5 1012
被撕碎了的回忆
被撕碎了的回忆 2020-11-22 13:26

Hi all I stumbled upon this piece of code today and I am confused as to what exactly happens and more particular in what order :

Code :

#include &l         


        
相关标签:
5条回答
  • 2020-11-22 13:47

    the c++ reference explains very well why that should never be done (is causing an UB or undefined behaviour) https://en.cppreference.com/w/cpp/language/operator_incdec

    #include <iostream>
    
    int main()
    {
        int n1 = 1;
        int n2 = ++n1;
        int n3 = ++ ++n1;
        int n4 = n1++;
    //  int n5 = n1++ ++;   // error
    //  int n6 = n1 + ++n1; // undefined behavior
        std::cout << "n1 = " << n1 << '\n'
                  << "n2 = " << n2 << '\n'
                  << "n3 = " << n3 << '\n'
                  << "n4 = " << n4 << '\n';
    }
    

    Notes

    Because of the side-effects involved, built-in increment and decrement operators must be used with care to avoid undefined behavior due to violations of sequencing rules.


    and in the section related to sequencing rules you can read the following:

    Undefined behavior:

    1) If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.

    i = ++i + 2;       // undefined behavior until C++11
    i = i++ + 2;       // undefined behavior until C++17
    f(i = -2, i = -2); // undefined behavior until C++17
    f(++i, ++i);       // undefined behavior until C++17, unspecified after C++17
    i = ++i + i++;     // undefined behavior
    

    2) If a side effect on a scalar object is unsequenced relative to a value computation using the value of the same scalar object, the behavior is undefined.

    cout << i << i++; // undefined behavior until C++17
    a[i] = i++;       // undefined behavior until C++17
    n = ++i + i;      // undefined behavior 
    
    0 讨论(0)
  • 2020-11-22 13:48

    Order of evaluation is unspecified. It is not left-to-right, right-to-left, or anything else.

    Don't do this.

    0 讨论(0)
  • 2020-11-22 14:07

    The answer to this question changed in C++17.

    Evaluation of overloaded operators are now sequenced in the same way as for built-in operators (C++17 [over.match.oper]/2).

    Furthermore, the <<, >> and subscripting operators now have the left operand sequenced before the right, and the postfix-expression of a function call is sequenced before evaluation of the arguments.

    (The other binary operators retain their previous sequencing, e.g. + is still unsequenced).

    So the code in the question must now output Value of test is : 0 Return value of function is : 1 Value of test : 1. But the advice "Don't do this" is still reasonable, given that it will take some time for everybody to update to C++17.

    0 讨论(0)
  • 2020-11-22 14:11

    The order of evaluation is unspecified, see http://en.wikipedia.org/wiki/Sequence_point

    This is the same situation as the example with the operator+ example:

    Consider two functions f() and g(). In C and C++, the + operator is not associated with a sequence point, and therefore in the expression f()+g() it is possible that either f() or g() will be executed first.

    0 讨论(0)
  • 2020-11-22 14:14

    The evaluation order of elements in an expression is unspecified (except some very particular cases, such as the && and || operators and the ternary operator, which introduce sequence points); so, it's not guaranteed that test will be evaluated before or after foo(test) (which modifies it).

    If your code relies on a particular order of evaluation the simplest method to obtain it is to split your expression in several separated statements.

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