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

发布于 2024-10-08 20:43:27 字数 398 浏览 9 评论 0原文

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

我在参考资料中缺少什么?

There are several questions about lifetime of constant reference on SO, but still I don't get it.

Is this piece of code valid?

struct S
{
    const int &ref;
    S( const int &x ) : ref(x) { }
};

int main( )
{
    S s( 0 );
    // ...
    use( s.ref );
    // ...
    return 0;
}

Intuitively I'd say no, since 0 should expire after the expression (S s(0);) is evaluated.

However both GCC and CLANG compile it fine, without warnings, and valgrind doesn't detect any runtime error.

What am I missing about references?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

谷夏 2024-10-15 20:43:27

根据 12.2/4 对我来说似乎无效:

有两种情况
临时对象被销毁
与结尾不同的点
充分表达。第一个上下文是
当表达式显示为
声明器定义的初始值设定项
一个对象。 在这种背景下,
临时保存结果
表达式应持续存在,直到
对象初始化完成


临时对象仅在 s 完全构造完成之前有效,而不是在调用 use 时有效。

Seems invalid to me according to 12.2/4 :

There are two contexts in which
temporaries are destroyed at a
different point than the end of the
fullexpression. The first context is
when an expression appears as an
initializer for a declarator defining
an object
. In that context, the
temporary that holds the result of the
expression shall persist until the
object’s initialization is complete
.

The temporary only gets to live until s is fully constructed, not until the point where use is called.

泪冰清 2024-10-15 20:43:27

正如其他人指出的那样,C++ 标准仅强制编译器在调用构造函数期间保留 0 临时值。实际上,gcc 在 main 函数的持续时间内保留临时文件,这会导致程序按预期运行。因此,不会出现警告或运行时错误。

但这只是偶然发生的。不要依赖这种行为。

As others have pointer out, the C++ standard only forces the compiler to keep the 0 temporary around for the duration for calling the constructor. In practice gcc keeps the temporary around for the duration of the main function which results in the program running as expected. For this reason, there are no warnings or runtime errors.

But this only works accidentally. Don't rely on this behaviour.

若水微香 2024-10-15 20:43:27

这里要注意的不是 const 而是引用。 const只是静态分析的一个工具。你需要小心参考文献,因为它们会咬人。

int& f()
{
    int i = 2;
    return i;
}

有时编译器足够聪明,可以警告您运行时会出现的问题,但有时却不然。无论哪种方式,编译器都不会对此发出警告。

The thing to note here is not the const but the reference. The const is just a tool for static analysis. You need to be careful with references because they can bite.

int& f()
{
    int i = 2;
    return i;
}

Sometimes the compiler is smart enough to warn you about issues that would show up at run time, but sometimes it's not. Either way the compiler doesn't have to warn you about this.

柠栀 2024-10-15 20:43:27

这是对代码的另一个调整,甚至 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 函数的堆栈帧中,因此当该函数返回时它会被销毁。这类似于返回局部变量的地址。

其他答案已经指出了为什么允许编译器这样做,我的代码只是一个说明。

Here is another tweak to your code that even valgrind complains about:

#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;
}

This normally puts the temporary in the stack frame of the foo function, so it gets destroyed when that function returns. This is similar to returning the address of a local variable.

The other answers have pointed out why the compiler is allowed to do this, my code is just an illustration.

卷耳 2024-10-15 20:43:27

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;
}

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

0 isn't a temporary, it's a literal. Try this small change to your program:

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;
}

I think the rule for references to a temporary only works for local variables, not members.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文