【问题标题】:Do rvalue references work just like lvalue references?右值引用是否像左值引用一样工作?
【发布时间】:2017-07-16 11:20:15
【问题描述】:

我想知道我的假设是否正确 -> 右值引用就像左值引用一样工作,只是它们只能绑定到右值,因此它们可以用于检测右值。

因此,当用作返回类型时,它就像左值引用一样工作,就像它们返回它们绑定到的实际对象一样。

当用作参数类型时,它们传递值而不进行任何复制。

我看到很多人问通过右值引用和通过值(以及通过左值引用)返回之间的区别是什么,但他们不能都回答说右值引用像左值引用一样工作,所以如果你知道使用左值引用时会发生什么,您可能知道使用右值引用时会发生什么,即您会知道通过右值引用返回返回实际对象,而按值返回返回副本,就像通过左值引用返回和通过返回之间的区别一样价值(大约)?

还是我错了?

【问题讨论】:

  • 我认为这是一个很好的摘要。
  • 我不清楚您是否意识到将引用(左值或右值)返回到本地(堆栈)变量将返回悬空引用,从而导致未定义的行为。
  • 返回 r 值引用可防止 RVO,因此是一种悲观(以及潜在危险)
  • @RichardCritten,我知道 :) 如果本地对象具有自动存储并且会在 return 语句中被销毁,这也很有意义。
  • @RichardHodges 我认为您假设该函数正在返回一个局部变量。如果函数返回对输入或成员变量的引用(如果它是对象方法),则 r 值引用可能是最快的,但仍然存在潜在危险。

标签: c++


【解决方案1】:

当任何命名对象被写入时,它被视为它的真实类型。

读取任何对象时,都将其视为左值引用。

从函数返回的对象没有名称,因此被视为其真实类型。

一切都由此而来。

【讨论】:

  • “真实类型”是什么意思?
  • @FacPam 我的意思是声明中提到的类型。例如。 X、X& 或 X&&。当读取任何这些类型的任何名称时,它是一个 X&
【解决方案2】:

就使用右值引用作为返回类型而言,它通常类似于左值引用,即您通常不应该这样做,因为您不能返回对局部变量的引用。但是,输入和输出中的右值引用组合可以实现一些有趣的事情:

Matrix operator+(const Matrix& lhs, const Matrix& rhs) {
    auto r = lhs;
    r += rhs;
    return r;
}

一些矩阵加法函数的典型签名。但是利用右值引用,我们可以像这样开始添加重载:

Matrix&& operator+(Matrix&& lhs, const Matrix& rhs) {
    lhs += rhs;
    return lhs;
}

第二个版本很整洁,因为没有副本,甚至没有任何动作!这对于左值引用实际上是不可行的,因为您不能确定是否可以继续使用/滥用输入的存储。所以右值引用确实开辟了一些通过引用返回的新机会,但它仍然是例外而不是常态。

【讨论】:

  • 如果我们没有复制省略会很酷,但我们有。所以完全没必要。在这种情况下,我们应该传递并返回副本。
  • 我无法与 17 交谈,但在 14 及之前返回副本并不总是具有相同的效果。例如,当您将多个函数调用链接在一起时,您可以看到这一点,复制省略往往只在一层深处起作用。
  • @RichardHodges 这是用 1z 编译的:coliru.stacked-crooked.com/a/87b64891a794dc0f。如果你不认为这个程序清楚地表明通过右值引用传递/返回可以节省你的移动通过值传递/返回,请解释。
  • 是的,我明白了,有机会以维护开销为代价优化嵌套操作(例如 w = x + y + z)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-31
  • 1970-01-01
相关资源
最近更新 更多