11
#include <iostream>
using namespace std;

int main()
{
    int x=80;
    int &y=x;
    cout<<"x"<<x<<" "<<"y"<<y++; 
    return 0;
}

The above code gave me the following output:

81 80

Can anyone explain me how the value of x changes to 81? The value of y is 80 and it later gets incremented to 81, but how did it reflect in x?

Did it reflect because y is a reference variable? Then the value should have been modified in both x and y?

Leonid Glanz
  • 1,261
  • 2
  • 16
  • 36
coder101
  • 840
  • 2
  • 11
  • 29

1 Answers1

15

You have undefined behaviour because your operations are between two consecutive sequence points (there are no sequence points between function arguments evaluation). You can loosely think of sequence points as "temporal" markers and between two consecutive ones you are not allowed to modify the same variable more than once.

Basically your code is equivalent to

std::cout << x << x++; // undefined behaviour

since y is just a reference (an alias) for x.

1.9 Program execution [intro.execution] (emphasize mine)

14) Every value computation and side effect associated with a full-expression is sequenced before every value computation and side effect associated with the next full-expression to be evaluated.

15) Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [ Note: In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations. — end note ] The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent (1.10), the behavior is undefined. [ Note: The next section imposes similar, but more complex restrictions on potentially concurrent computations. —endnote]

When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [ Note: Value computations and side effects associated with different argument expressions are unsequenced. — end note ] Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.9 Several contexts in C++ cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit. [ Example: Evaluation of a new-expression invokes one or more allocation and constructor functions; see 5.3.4. For another example, invocation of a conversion function (12.3.2) can arise in contexts in which no function call syntax appears.

Related: https://stackoverflow.com/a/10782972/3093378

Community
  • 1
  • 1
vsoftco
  • 55,410
  • 12
  • 139
  • 252
  • I think you have an extra not there, they are between the same two sequence points (i.e. there is not a sequence point between the two operations) – Borgleader May 15 '15 at 19:37
  • I don't believe that this is quite true for references. After all, if the programmer recieves two references as parameters, how can he know if they alias? I'm not sure if the rules for operations on references are the same as for regular variables. – Puppy May 15 '15 at 20:14
  • @Puppy I agree that the client cannot know if `a` and `b` refer to the same object, but if they happen to, then I believe the compiler treats them internally as two (different) pointers to the referred object. Is modifying pointers referring to the same object between consecutive sequence points well defined? I remember that the standard clearly refers to "side effects between sequence points", so you'll have side effects here. Edited with something I think it is relevant from the standard. – vsoftco May 15 '15 at 20:27
  • @Puppy that's exactly why it is *undefined behaviour* . If the standard were changed so that `cout << c << c++` has well-defined semantics then the compiler would have to pessimize a function `f(int &x, int &y) { cout << x << y++; }`. As things stand now, the compiler can assume x and y don't alias when generating code for that function. The programmer could test `&x == &y` if he/she wants to know. – M.M Nov 25 '15 at 22:37