6

在尝试确保两个变量的升序时,我在 Visual Studio 2012 C++ 编译器中遇到了奇怪的异常,可以通过以下代码片段说明

    double x1 = 2;
    double x2 = 1;
    std::tie(x1, x2) = std::minmax(x1, x2);
    std::cout << "x1 = " << x1 << ",   x2 = " << x2 << "\n";

人们会认为 x1 是 1,x2 是 2。但事实并非如此。反而

    //output:
    //x1 = 1,   x2 = 1

有什么好的解释,只是为了确保不再陷入类似的陷阱?

4

2 回答 2

4

std::minmax通过引用返回其参数。您的语句发生的情况是,首先x1分配 的值x2,即 1。然后,x2分配 的值x1,即 2,但现在为 1。

如果你要内联所有内容,它可能看起来像这样:

// 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

我认为您的部分困惑来自于认为(或希望)这些作业会同时发生,但事实并非如此。当您分配 atuple或 apair时,子对象按从左到右的顺序分配。

于 2013-06-29T13:14:40.063 回答
3

问题是std::minmax()接受两个引用并返回一对引用。特别是,在您的情况下,它将返回一对,其中第一个元素是对 的引用x2,第二个元素是对 的引用x1

另一方面,在作业的左侧,您有:

std::tie(x1, x2)

这也创建了一对引用(好吧,实际上是两个引用的元组,但这没关系),但这一次对的第一个元素是对 的引用x1,而第二个元素是对 的引用x2

然后,您将返回的对分配给返回std::minmax()的对std::tie,这意味着首先x1分配x2(即1)的值;之后x2被分配的值x1(再一次,那是因为std::minmax()返回了一对引用,所以该对的第二个元素“看到”了对 的赋值的副作用x1),即 now 1

这应该解释输出。

于 2013-06-29T13:15:46.253 回答