【问题标题】:Reference initialization - temporary bound to return value引用初始化 - 临时绑定到返回值
【发布时间】:2021-05-30 12:22:13
【问题描述】:

在 cppreference.com (Lifetime of a temporary) 的一篇关于引用初始化的文章中,它说:

在 return 语句中临时绑定到函数的返回值不会被扩展:它在 return 表达式的末尾立即被销毁。这样的函数总是返回一个悬空引用。

此摘录解决了通过绑定对临时对象的引用来延长其生命周期的例外情况。他们实际上是什么意思?我想过类似的事情

#include <iostream>

int&& func()
{
    return 42;
}

int main()
{
    int&& foo = func();
    std::cout << foo << std::endl;

    return 0;
}

所以foo 应该引用临时的 42。根据摘录,这应该是一个悬空引用 - 但这会打印 42 而不是一些随机值,所以它工作得很好。

我确定我在这里弄错了,如果有人能解决我的困惑,我将不胜感激。

【问题讨论】:

  • 取消引用悬空引用是未定义的行为:包括打印 42、擦除硬盘驱动器或发动核战争。
  • 我无法重现这个:coliru.stacked-crooked.com/a/7211be5336782f11 但是,这只是未定义的行为,一切都可能发生。
  • 对不起,我是新手。所以这就是他们所说的“在 return 语句中临时绑定到函数的返回值”?只是碰巧Visual C++ 以打印42 的方式编译它?
  • @Ruperrrt "未定义的行为" 表示没有行为的定义。这并不意味着行为必须与期望不同(这本身就是一种定义)。一般来说,编译器不会特意对带有 UB 的程序做出反应,他们只是为有效程序执行规则,而对于无效程序,芯片可能会落下。

标签: c++ rvalue-reference temporary-objects


【解决方案1】:

你的例子很好,但你的编译器不是。

临时值通常是文字值、函数返回值,但也是使用语法“class_name(constructor_arguments)”传递给函数的对象。例如,在将 lambda 表达式引入 C++ 之前,要对事物进行排序,可以使用重载的 operator() 定义一些结构 X,然后进行如下调用:

std::sort(v.begin(), v.end(), X());

在这种情况下,您希望使用 X() 构造的临时对象的生命周期将在结束指令的分号处结束。

如果您调用一个需要 const 引用的函数,例如 void f(const int &amp; n),带有临时性,例如f(2),编译器创建一个临时的int,用2 对其进行初始化,并将对这个临时的引用传递给函数。您希望这个临时文件以 f(2); 中的分号结束其生命。

现在考虑一下:

int && ref = 2;
std::cout << ref;

此代码完全有效。但是请注意,这里编译器还创建了一个int 类型的临时对象,并将其初始化为2。这是ref 绑定的临时对象。但是,如果临时的生命周期仅限于在其中创建它的指令,并以标记指令结束的分号结束,那么下一条指令将是一场灾难,因为cout 将使用悬空引用。因此,像上面提到的临时人员将是相当不切实际的。这就是“延长临时工寿命”所需要的。我怀疑编译器在看到int &amp;&amp; ref = 2 之类的内容时允许将其转换为类似的内容

int tmp = 2;
int && ref = std::move(tmp);
std::cout << ref; // equivalent to std::cout << tmp;

如果没有生命周期扩展,这可能看起来像这样:

{
 int tmp = 2;
 int && ref = std::move(tmp);
}
std::cout << ref; // what is ref? 

在 return 语句中做这样的把戏是没有意义的。没有合理、安全的方法来延长函数本地对象的生命周期。

顺便说一句。大多数现代编译器都会发出警告并减少您的功能

int&& func()
{
    return 42;
}

int&& func()
{
    return nullptr;
}

在尝试取消引用返回值时立即出现段错误。

【讨论】:

  • 非常感谢您清晰详细的回答!
  • 有一个向上的箭头(或三角形)可以点击;-)
  • 我的点赞数不可见,因为我的声望低于 15。 :(
  • 或许你可以接受这个答案?它应该在这两个三角形附近的某个地方... :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-23
  • 2012-07-18
  • 2021-10-13
  • 1970-01-01
  • 2023-03-30
  • 2012-02-12
相关资源
最近更新 更多