#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()返回的临时对象的生命周期是什么?这是&#34; ref&#34;或临时引用static_cast(fnc()),它在语句结束时被销毁?
gcc的输出(fnc()的生命周期是&#34; ref&#34;)的生命周期:
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"
标准是什么?
答案 0 :(得分:5)
我相信Visual Studio在这里是正确的,这在defect report #1376中有所说明:
在像
这样的声明中T&& r = static_cast<T&&>(T());
目前尚不清楚T临时的寿命应该是多少。 根据5.2.9 [expr.static.cast]第4段,static_cast是 相当于发明临时变量t的声明。该 临时的生命周期延长到t的生命周期,但事实并非如此 清楚那个生命应该是什么,也不是后来的t的约束 到r会影响原来临时的生命周期。 (也可以看看 问题1568。)
讨论包括这个结论:
引用绑定到static_cast的xvalue结果,因此不会扩展临时的生命周期,此示例会导致悬空引用。
和defect report 1568更具体地涵盖了这个案例:
根据12.2 [class.temporary]第4-5段,
有两种情况下,临时演员在与完整表达结束时不同的地方被摧毁......
第二个上下文是引用绑定到临时的。引用绑定的临时值或临时值 引用绑定到的子对象的完整对象 坚持参考的一生......
目前尚不清楚这是否适用于以下示例:
struct S { }; const S& r = (const S&)S();
并且回复是:
此问题与问题1376重复。
所以在这种情况下:
const CL& ref=static_cast<const CL&>(fnc());
引用绑定到static_cast
的结果而不是CL
的结果,因此CL
是一个悬空引用。
供参考C ++ 11标准草案5.2.9
[expr.static.cast] 草案中的相关文本:
否则,可以使用static_-形式的static_cast将表达式e显式转换为类型T. (e)如果声明T t(e);对于一些发明的临时变量t(8.5),其形式良好。该 这种显式转换的效果与执行声明和初始化相同 使用临时变量作为转换的结果。如果和,表达式e用作glvalue 只有初始化将它用作glvalue。