const 引用是否绑定到另一个从临时悬挂引用转换而来的引用?

Is a const reference bound to another reference which is cast from temporary a dangling reference?

下面是代码片段:

#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

所以 return 值似乎比 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(无关部分被我删掉):

The third context is when a reference is bound to a temporary object. The temporary object to which the reference is bound or the temporary object that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference if the glvalue to which the reference is bound was obtained through one of the following:

  • ...

  • a const_­cast ([expr.const.cast]), static_­cast ([expr.static.cast]), dynamic_­cast ([expr.dynamic.cast]), or reinterpret_­cast ([expr.reinterpret.cast]) converting, without a user-defined conversion, a glvalue operand that is one of these expressions to a glvalue that refers to the object designated by the operand, or to its complete object or a subobject thereof,

  • ...

... [ Note: An explicit type conversion ([expr.type.conv], [expr.cast]) is interpreted as a sequence of elementary casts, covered above. [ Example:

const int& x = (const int&)1;  // temporary for value 1 has same lifetime as x

— end example ] — end note ]

您的代码格式正确。


在C++14之前,标准中对这种情况的措辞不明确,存在缺陷问题1376. This issue clarifies the lifetime of the temporary object should not be extended in such case. However, this clarification is superseded by issue 1299(C++17中也没有解决,但在当前草案)。

所以可以断定在issue 1299解决之前,是GCC 4.6以后版本的bug。 GCC 还有一个 bug report 52202