我想到了C++中的一个奇怪作弊。通常,我无法将引用走私到范围之外,因为无法在包含范围中定义未初始化的引用。但是,我可以定义一个指向包含引用的类的指针,无法对其进行初始化,然后为它分配一些初始化为局部变量的动态内存的地址。即使该动态对象包含对本应超出范围的变量的引用,但指向的对象仍然具有具有相同值的有效引用!即使我告诉它是-pedantic,g++也不会抱怨,所以我认为它是有效的。但是如何,为什么?

struct int_ref
{
  int &x;
  int_ref(int &i): x(i) {}
};

#include <iostream>
using namespace std;

int main(void)
{
  int_ref *irp;
  int i = 1;
  int_ref a(i); // Creates an int_ref initialized to i
  irp = &a; // irp is now a pointer to a reference!
  // Prints 1
  cout << "irp->x = " << irp->x << " (i = " << i << ")" << endl;
  i = 2;
  // Prints 2
  cout << "irp->x = " << irp->x << " (i = " << i << ")" << endl;
  int j = 3;
  int_ref b(j);
  irp = &b;
  // Prints 3
  cout << "irp->x = " << irp->x << " (i = " << i << ", j = " << j << ")" << endl;
  i = 1;
  // Still prints 3
  cout << "irp->x = " << irp->x << " (i = " << i << ", j = " << j << ")" << endl;
  {
    int k = 4;
    irp = new int_ref(k);
    // k goes out of scope
  }
  int k = 1; // Doesn't affect the other k, of course
  // Prints 4 ?!
  cout << "irp->x = " << irp->x << " (i = " << i << ", j = " << j << ")" << endl;
}

编辑:实际上,这可能是(如答案中所建议的)未诊断的悬挂引用。如果我这样定义int_ref怎么办:
struct int_ref
{
  const int &x;
  int_ref(const int &i): x(i) {}
};
const引用不必引用左值,因此没有明确定义的悬挂对象。代码是否仍未定义?

最佳答案

仅仅因为您的编译器没有为您的程序发出诊断信息,并不意味着您的程序是好的,有效的和安全的。

最后一行调用“未定义行为”,因为您有一个悬挂的引用。不需要由编译器诊断,但是也不能使之正确。您可能会得到4(只是碰巧仍然在内存中的那个位置),您可能会获得一些其他值,您可能会遇到分段错误,或者您的PC可能会爆炸。

请不要这样做。

术语注释:这里没有“引用指针”(不存在这样的东西),只有指向int_ref的指针。

10-04 12:07
查看更多