关于SO的常量引用的生命周期有几个问题,但我仍然没有得到它。
这段代码有效吗?
struct S
{
const int &ref;
S( const int &x ) : ref(x) { }
};
int main( )
{
S s( 0 );
// ...
use( s.ref );
// ...
return 0;
}
直观地说我不会,因为0
应该在表达式(S s(0);
)被评估之后到期。
然而GCC和CLANG都编译得很好,没有警告,并且valgrind没有检测到任何运行时错误。
我对参考资料缺少什么?
答案 0 :(得分:4)
对我来说似乎无效:
有两种情况 临时的人被摧毁了 不同点比结束了 fullexpression。第一个背景是 表达式显示为 声明符定义的初始化程序 一个对象。 在这种情况下, 暂时的,持有的结果 表达将持续到 对象的初始化已完成。
临时只有s
完全构建才会生效,直到调用use
为止。
答案 1 :(得分:2)
当其他人指出时,C ++标准只强制编译器在调用构造函数的过程中保持0
临时。在实践中,gcc在main
函数的持续时间内保持临时性,这导致程序按预期运行。因此,没有警告或运行时错误。
但这只是偶然的。不要依赖这种行为。
答案 2 :(得分:1)
这里要注意的不是const
而是参考。 const只是静态分析的工具。你需要小心引用,因为它们可以咬人。
int& f()
{
int i = 2;
return i;
}
有时编译器足够聪明,可以警告您在运行时出现的问题,但有时情况并非如此。无论哪种方式,编译器都不会拥有来警告你。
答案 3 :(得分:1)
这是对你的代码的另一个调整,甚至valgrind抱怨:
#include <iostream>
struct S
{
const int &ref;
S( const int &x ) : ref(x) { }
};
S* foo()
{
return new S(0);
}
int main( )
{
S* s = foo();
std::cout << s->ref << std::endl;
return 0;
}
这通常将临时放在foo
函数的堆栈帧中,因此当该函数返回时它会被销毁。这类似于返回局部变量的地址。
其他答案指出了为什么允许编译器执行此操作,我的代码只是一个例子。
答案 4 :(得分:0)
0
不是一个临时的,它是一个文字。尝试对您的程序进行这一小改动:
struct S
{
const int &ref;
S( const int &x ) : ref(x) { }
};
int f()
{
return 0;
}
int main( )
{
S s( f() );
// ...
use( s.ref );
// ...
return 0;
}
我认为引用临时的规则仅适用于局部变量,而不适用于成员。