#include <iostream>
int& addOne(int& x)
{
x += 1;
return x;
}
int main()
{
int x {5};
addOne(x) = x;
std::cout << x << ' ' << addOne(x);
}
I’m currently in the middle of learning about lvalues and rvalues and was experimenting a bit, and made this which seems to be getting conflicting results.
https://godbolt.org/z/KqsGz3Toe produces an out put of "5 6", as does Clion and Visual Studio, however https://www.onlinegdb.com/49mUC7x8U produces a result of "6 7"
I would think that because addOne is calling x as a reference, it would explicitly change the value of x to 6 despite being called as an lvalue. What should the correct result be?
>Solution :
Since C++17 the order of evaluation is specified such that the right-hand side of assignment is evaluated first and that the << operator is evaluated left-to-right.
So in
addOne(x) = x;
first the value of the right-hand side is evaluated, yielding 5. Then the function addOne is called and it doesn’t matter what it does with x since it returns a reference to it, to which the right-hand value 5 is assigned.
Then in the line
std::cout << x << ' ' << addOne(x);
we first evaluate and output x, resulting in 5, and then call addOne, resulting in 6.
The output 5 6 is the only correct one since C++17.
Before C++17, the evaluation order of the two sides of the assignment operator was unsequenced.
Having a scalar modification unsequenced with a value computation (on the right-hand side) causes undefined behavior normally.
But since you put the increment of x into a function, an additional rule saying that the execution of a function body is only indeterminately sequenced with other evaluations in the calling context removes this source of undefined behavior.
This means however, that we won’t know whether x is evaluated first and then addOne(x) or the other way around.
Therefore after the line, x may be 5 or 6.
Then in the line
std::cout << x << ' ' << addOne(x);
pre-C++17 the same issue applied. The evaluations of the arguments to << were indeterminately sequenced, rather than left-to-right and so addOne(x) could be evaluated before the left-hand x.
Therefore possible program output could be either of the following:
5 6
6 6
6 7
7 7
You can specify to use C++17 (or newer versions like C++20) with the -std=c++17 flag to the compiler if you are using GCC or Clang and /std:c++17 if you are using MSVC. Which standard version is chosen by-default depends on the compiler and compiler version.