为什么对常量临时值的局部引用似乎比它定义的方法长寿?

Why does a local reference to a constant temporary value seem to outlive the method it's defined in?

我很困惑为什么下面的代码编译成功并且似乎 运行 正确显示 7 两次。我怀疑这两个调用中都潜伏着一些未定义的行为。

#include <iostream>

template <typename T>
const T& max(const T& x, const T& y)
{
    return (x > y) ? x : y;
}

int main()
{
    const int &var1 = max(3, 7);
    std::cout << var1 << '\n';

    int var2 = max(3, 7);
    std::cout << var2 << '\n';

    return 0;
}

在此示例中,两个局部引用变量分别引用临时值 3、7。然后方法 returns 引用最大值,即 7。但是,当方法 returns 时,引用不再有效。它是悬空的!所以,即使 var1 似乎指的是 7 的值,难道它不被认为是未定义的,不能保证 7 稍后会出现吗?

同样,即使 var2 只是应该获取 max() 输出的副本,该方法的 return 语句 return 是一个悬空引用!所以,我认为即使是 var2 也不可靠,因为它从垃圾位置获取副本。

那么,我是否应该考虑两个 cout 语句都显示垃圾(尽管 7 显示了两次)?

在您的示例中,使用 var1 表现出未定义的行为,因为 var1 是悬空引用。使用 var2 即可。

"The max() method creates two local reference variables to store temporary values 3, 7"

不,事实并非如此。 max()caller 创建了两个临时对象,并将对它们的引用传递给 max()max 本身并不知道它的参数是对临时对象的引用,还是对诚实的长期对象的引用。所以你的例子大致等同于:

const int* p;
{
  int temp1 = 3;
  int temp2 = 7;
  p = &max(temp1, temp2);  // p points to temp2
}
const int& var1 = *p;  // p is dangling by now; temp2 has been destroyed

(这里使用中间指针只是因为没有延迟绑定引用的语法)。


int var2;
{
  int temp1 = 3;
  int temp2 = 7;
  var2 = max(temp1, temp2);  // var2 = 7
}
// temp2 is gone, but var2 safely stores a copy of it.