C ++:对临时的常量引用

时间:2010-12-23 22:23:27

标签: c++ reference const temporary lifetime

关于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没有检测到任何运行时错误。

我对参考资料缺少什么?

5 个答案:

答案 0 :(得分:4)

根据12.2 / 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;
}

我认为引用临时的规则仅适用于局部变量,而不适用于成员。