8

如果我编写以下代码:

#include <iostream>

using namespace std;

int main()
{
  cout << &(int &&)123 << endl;
  return 0;
}

然后g++抱怨:

foo.cc: In function ‘int main()’:
foo.cc:7:20: error: taking address of xvalue (rvalue reference)

好的,感谢什么是右值、左值、xvalues、glvalues 和 prvalues?我知道一个 xvalue 意味着它即将“过期”,这是有道理的。但现在如果我这样做:

#include <iostream>

using namespace std;

int main()
{
  const int &x = (int &&)123;
  cout << &x << endl;
  return 0;
}

这个“工作”很好,会打印一个地址。所以,我有几个问题:

  1. 如果值即将过期,为什么我可以引用它?引用不会使原始对象保持活动状态(对吗?)。
  2. 这样的引用会导致未定义的行为吗?例如,因为我们引用了一个可能已经被破坏的对象?

一般来说,有没有办法知道右值引用的生命周期?

4

2 回答 2

10

也许我一个人,但我认为这并不安全:

const int &x = (int &&)123;

仅当引用由直接引用临时对象的表达式初始化时,生命周期延长规则才适用。换句话说,表达式必须带有“临时”属性。如果省略(int&&), 则为了绑定到引用,编译器将隐式创建一个纯右值表达式,该表达式引用一个由值初始化的临时对象,123然后应用生命周期延长。

但是如果你在两者之间混合右值引用,编译器就无法在编译时知道是否要延长被引用对象的生命周期。

int a = 0;
const int &x = ((rand() == 42) ? (int&&)123 : (int&&)a);

因此,我认为您的代码具有未定义的行为,因为您评估了一个悬空引用(即使只是为了获取它的地址)。

于 2012-02-27T22:09:11.460 回答
2

第 12.2 条第 4-5 段说,在第二个示例中延长了生命周期

在两种情况下,临时对象在与完整表达式结束时不同的点被销毁。...

第二个上下文是引用绑定到临时的。引用绑定的临时对象或引用绑定的子对象的完整对象的临时对象在引用的生命周期内持续存在,除非:(
此处不适用任何例外)

于 2012-02-27T16:21:43.327 回答