While trying to ensure ascending order of two variables, I've encountered strange anomaly in Visual Studio 2012 C++ compiler that can be illustrated by the following code snippet
double x1 = 2;
double x2 = 1;
std::tie(x1, x2) = std::minmax(x1, x2);
std::cout << "x1 = " << x1 << ", x2 = " << x2 << "\n";
one would expect that x1 is 1 and x2 is 2. But they are not. Instead
//output:
//x1 = 1, x2 = 1
Is there any good explanation, just to be sure not to fall into similar trap again?
std::minmax
returns its arguments back by reference. What happens with your statement is, first x1
gets assigned the value of x2
, which is 1. Then, x2
gets assigned the value of x1
, which was 2, but is now 1.
If you were to inline everything, it might look something like this:
// using pointers because references can't be rebound
double *less, *greater;
if (x1 <= x2)
{
less = &x1;
greater = &x2;
}
else
{
// in your case, this is the branch taken
less = &x2;
greater = &x1;
}
x1 = *less; // less points to x2, so now both x1 and x2 = 1
x2 = *greater; // greater points to x1, and x1 = 1, so this assignment is redundant
I think part of your confusion comes from thinking (or hoping) that the assignments would happen simultaneously, but they don't. When you assign a tuple
or a pair
, the sub-objects are assigned in order, from left to right.
The problem is that std::minmax()
accepts two references and returns a pair of references . In particular, in your case it will return a pair where the first element is a reference to x2
, and the second element is a reference to x1
.
On the left side of the assignment, on the other hand, you have:
std::tie(x1, x2)
Which also creates a pair of references (ok, a tuple of two references actually, but that doesn't matter), but this time the first element of the pair is a reference to x1
, while the second element is a reference to x2
.
Then, you assign the pair returned by std::minmax()
to the pair returned by std::tie
, which means that x1
gets assigned the value of x2
(which is 1
) first; after that , x2
gets assigned the new value of x1
(once again, that's because std::minmax()
returned a pair of references, so the second element of that pair "sees" the side-effect of the assignment to x1
), which is now 1
.
This should explain the output.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.