以下是代码段:
#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;
}
<{3>}中的输出
destruct B
destruct B
1
因此返回值似乎比cout
操作更早破坏。所以instance
似乎是一个悬空参考。
如果我们将const B& instance = (const B&)func();
更改为const B& instance =func();
,则结果为
destruct B
1
destruct B
作为补充,如果我在vs2015中测试代码,那么输出就是最后一个。但是,如果在this online compiler中进行测试,则输出为前者,但后者为4.6之后的版本。所以我想知道在线编译器是错误的还是引用实际上是悬空的。
答案 0 :(得分:8)
根据最新的草案[class.temporary]/6(我无视相关部分):
第三个上下文是引用绑定到临时对象的时间。如果绑定引用的glvalue是通过以下之一获取的,则引用绑定到的临时对象或作为绑定引用的子对象的完整对象的临时对象将持续参考的生命周期:
...
const_cast([expr.const.cast]),static_cast([expr.static.cast]),dynamic_cast([expr.dynamic.cast])或reinterpret_cast([expr.reinterpret.cast] )在没有用户定义的转换的情况下,将作为这些表达式之一的glvalue操作数转换为glvalue,该glvalue引用操作数指定的对象,或者指向其完整对象或其子对象,
...
... [注意:显式类型转换([expr.type.conv],[expr.cast])被解释为一系列基本演员表,如上所述。 [实施例:
const int& x = (const int&)1; // temporary for value 1 has same lifetime as x
- 结束示例] - 结束注释]
您的代码格式正确。
在C ++ 14之前,标准中的措辞不清楚这种情况,并且存在缺陷问题1376。此问题阐明了在这种情况下不扩展临时对象的生命周期。但是,这一澄清已被问题1299所取代(即使在C ++ 17中也没有包括其解决方案,但在当前的草案中)。
因此,你可以在问题1299的解决之前得出结论,这是GCC版本4.6之后的版本的错误。海湾合作委员会还有一个bug report 52202。