以下代码正常执行(请参阅here):
#include <iostream>
struct A {
int i;
A():i(1){}
operator int&() { return i; }
};
int& rri = A();
int main()
{
int& ri = A();
std::cout << ri << '\n';
std::cout << rri << '\n';
}
打印
1
1
正如所料。但是,如果我在main()中注释掉前两个语句,只留下
std::cout << rri << '\n';
代码打印0
。
修改
让我们假设问题出在我的代码上。但后来我问:标准中8.5.3 / 5中第三个要点的目的是什么,我在下面复制了:
对类型“cv1 T1”的引用由类型的表达式初始化 “cv2 T2”如下:
如果引用是左值引用和初始化表达式
- 引用兼容
是左值(但不是位字段),“cv1 T1”与“cv2 T2”或
有一个类类型(即T2是一个类类型),其中T1与T2没有引用相关,可以转换为类型的左值 “cv3 T3”,其中“cv1 T1”与“cv3 T3”引用兼容(通过列举适用的转换函数(13.3.1.6)并选择最佳的转换函数来选择此转换 重载决议(13.3)),
然后引用绑定到 初始化表达式lvalue在第一种情况下和左值 在第二种情况下转换的结果(或者,在任何一种情况下,转换为 对象的适当基类子对象)。 [注意:通常 lvalue-to-rvalue(4.1),array-to-pointer(4.2)和 函数到指针(4.3)不需要标准转换,和 因此,当对左值的这种直接结合时,它被抑制 完成。 - 尾注]
答案 0 :(得分:11)
未定义的行为:ri
和rri
都被初始化为引用临时成员,并立即销毁。
悬空引用指向可能被另一个对象重用的某些内存,在这种情况下,您可能会看到该对象的数据。或者您可能会看到其他一些未定义的行为。