对临时引用的 const 引用

const reference to temporary reference

#include <iostream>
using namespace std;

struct CL
{
    CL()
    {
        cout<<"CL()"<<endl;
    }
    CL(const CL&)
    {
        cout<<"CL(const CL&)"<<endl;
    }
    ~CL()
    {
        cout<<"~CL()"<<endl;
    }
};

CL cl;

CL fnc()
{
    return cl;
}

int main() {
    cout<<"start"<<endl;
    const CL& ref=static_cast<const CL&>(fnc());
    //...Is "ref" valid here??
    cout<<"end"<<endl;
    return 0;
}

fnc() 返回的临时对象的生命周期是多少?它是 "ref" 的生命周期还是临时引用 static_cast(fnc()) 的生命周期,它在语句结束时被销毁?

gcc 的输出(fnc() 的生命周期是 "ref" 的生命周期):

CL()  //global object "cl"
start
CL(const CL&)
end
~CL()
~CL() //global object "cl"

VS2013的输出(fnc()的生命周期是临时引用的生命周期):

CL()  //global object "cl"
start
CL(const CL&)
~CL()
end
~CL() //global object "cl"

标准正确的是什么?

我相信 Visual Studio 在这里是正确的,这在 defect report #1376 中有说明:

In a declaration like

T&& r = static_cast<T&&>(T());

it is not clear what the lifetime of the T temporary should be. According to 5.2.9 [expr.static.cast] paragraph 4, the static_cast is equivalent to a declaration of an invented temporary variable t. The lifetime of the temporary is extended to that of t, but it is not clear what that lifetime should be, nor if the subsequent binding of t to r would affect the lifetime of the original temporary. (See also issue 1568.)

并且讨论包括这个结论:

The reference is bound to the xvalue result of the static_cast, so the lifetime of the temporary is not extended and this example results in a dangling reference.

defect report 1568 更具体地涵盖了这种情况:

According to 12.2 [class.temporary] paragraphs 4-5,

There are two contexts in which temporaries are destroyed at a different point than the end of the full-expression...

The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference...

不清楚这是否适用于如下示例:

struct S { };
const S& r = (const S&)S();

响应是:

This issue is a duplicate of issue 1376.

所以在这种情况下:

const CL& ref=static_cast<const CL&>(fnc());

引用绑定到 static_cast 的结果而不是 CL,因此 CL 是一个悬空引用。

参考C++11标准部分草案的相关文本5.2.9 [expr.static.cast]:

Otherwise, an expression e can be explicitly converted to a type T using a static_cast of the form static_- cast(e) if the declaration T t(e); is well-formed, for some invented temporary variable t (8.5). The effect of such an explicit conversion is the same as performing the declaration and initialization and then using the temporary variable as the result of the conversion. The expression e is used as a glvalue if and only if the initialization uses it as a glvalue.