I thought of a strange cheat in C++. Normally, I can't smuggle a reference out of a scope because I can't define an uninitialized reference in the containing scope. However, I can define a pointer to a class containing a reference, fail to initialize it, and then assign it the address of some dynamic memory initialized to a local variable. Even though that dynamic object contains a reference to a variable that is supposed to go out of scope, the pointed-to object still has a valid reference with the same value! g++ doesn't complain even if I tell it to be -pedantic
, so I assume it's valid. But how, and why?
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;
}
Edit: This may in fact be (as suggested in the answers) an undiagnosed dangling reference. What about if I define int_ref
like this:
struct int_ref
{
const int &x;
int_ref(const int &i): x(i) {}
};
A const
reference need not refer to an lvalue, so there is no well-defined concept of a dangling one. Is the code still undefined?