【问题标题】:Returning an rvalue reference that is passed to a function as an argument返回作为参数传递给函数的右值引用
【发布时间】:2020-11-27 20:26:55
【问题描述】:

我想了解我是否可以安全地返回作为参数传递给函数的右值引用,并且它不会随着堆栈展开而被破坏。

struct Struct { int m; };

Struct& f(Struct&& rvalue)
{ 
    std::cout << &rvalue << '\n';
    return rvalue;
}

void main()
{
    Struct& lvalue1 = f(Struct{ 1 });
    std::cout << &lvalue1 << '\n';
    Struct& lvalue2 = f(Struct{ 2 });
    std::cout << &lvalue2 << '\n';

    std::cin.get();
}

输出:

00A3F844
00A3F844
00A3F838
00A3F838

此代码为右值生成不同的地址。这是否意味着 Struct 对象的实际构造发生在函数调用之前,我可以安全地做这种事情?

【问题讨论】:

  • 请注意,在 C++ 中,main 函数的返回类型必须为 int
  • @François Andrieux 这是标准吗?据我所知,Windows 不使用 main 的返回值。
  • It is required by the standard。平台可以提供额外的重载,但即使是那些需要返回类型int
  • 很高兴知道。感谢您的链接。

标签: c++ function reference stack rvalue


【解决方案1】:

我可以安全地做这种事情吗?

没有。 Struct{ 1 }Struct{ 2 } 构造 temporary objects 在完整表达式后被销毁。这意味着引用 lvalue1lvalue2 总是悬空的。对它们的取消引用会导致未定义的行为。

所有临时对象都作为评估完整表达式的最后一步被销毁,完整表达式(词法上)包含它们的创建点

【讨论】:

  • 你能安全地做Struct&amp;&amp; f(Struct&amp;&amp; rvalue) { return std::move(rvalue); },然后再次将返回值绑定到一个右值引用,即Struct&amp;&amp; doesThisWork = f(Struct{1});吗?我认为应该,但不确定...
  • 我想知道为什么第一个结构没有被第二个覆盖,然后堆栈展开。在 f 调用之后,我可以访问 m 个成员并分别获得 12
  • @lubgr 不 - 它仍然绑定到将被销毁的临时对象。
  • @OleksijPlotnyc'kyj 未定义行为是未定义的 - 没有必要对此进行推理。
  • @lubgr 否。对于reference initialization一般来说,临时的生命周期不能通过“传递”进一步延长:第二个引用,从临时被绑定,不影响其生命周期。.
猜你喜欢
  • 2018-09-09
  • 1970-01-01
  • 2014-09-09
  • 1970-01-01
  • 2013-09-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-21
相关资源
最近更新 更多