【发布时间】:2018-11-05 15:31:27
【问题描述】:
下面是sn-p的代码:
#include <iostream>
using namespace std;
struct B{
int b;
~B(){cout <<"destruct B" << endl;}
};
B func(){
B b;
b.b = 1;
return b;
}
int main(){
const B& instance = (const B&)func(); //is `instance` a dangling reference?
cout <<instance.b<<endl;
return 0;
}
在this online compiler 中的输出是
destruct B
destruct B
1
所以返回值似乎比cout 操作更早被破坏。所以instance 似乎是一个悬空引用。
如果我们把const B& instance = (const B&)func();改成const B& instance =func();,那么结果就是
destruct B
1
destruct B
作为补充,如果我在vs2015中测试代码,那么输出就是最后一个。但是,如果在gcc(before 4.6)中测试,输出的是前者,但在4.6之后的版本中输出的是后者。所以想知道是网上的编译器有错还是引用其实是悬空的。
【问题讨论】:
-
你已经在标题中回答了你自己的问题:你的参考没有绑定到临时的。
-
来自[class.temporary]/6:
const int& x = (const int&)1; // temporary for value 1 has same lifetime as x -
啊,看起来该语言已通过缺陷报告wg21.link/cwg1299 追溯更改,因此 C++11 现在也可以“新”方式工作。 (DR 说以前只有纯右值被认为是“临时的”,而新规则更加宽松。)
-
@bigxiao:它曾经也是 C++11 中的一个悬空引用,直到 2017 年 7 月它才成为有效的 C++11。缺陷报告适用于旧版标准的方式非常模糊,因为正式它们只适用于唯一的当前标准。每份出版物均取代前一份出版物。 DR 的措辞不能从字面上适用于没有 glvalues 的 C++03,但您的供应商现在可以选择基于此 DR 延长 C++03 模式下的生命周期。我认为这是一个合理的解释。
-
@bigxiao:因为缺陷报告的工作方式。请注意,严格来说,它仍然存在于早期的 C++17 中——已发布的 C++17 包含旧的行为;缺陷报告仅在 C++17 完成后才被接受(例如,参见 wg21.link/N4659)。但“标准”是指“已发布的文档连同所有随后接受的缺陷报告”。
标签: c++ language-lawyer object-lifetime reference-binding