返回 const 引用和 rvalue 引用之间的区别

Posted

技术标签:

【中文标题】返回 const 引用和 rvalue 引用之间的区别【英文标题】:Difference between returning a const reference and rvalue reference 【发布时间】:2013-03-28 12:21:45 【问题描述】:

如果我没记错的话,我认为 const 引用和 rvalue 引用都可以绑定到 rvalue。返回前者的函数和返回后者的函数之间有什么实际区别吗?

编辑。我不能修改前者,但为什么我会对修改右值感兴趣?有意义吗?

【问题讨论】:

对,我猜是这样。我会编辑帖子... 如果你说的是returning,那么你可能不想返回一个rvalue-references。虽然可能有一些用例可以通过返回 rvalue-reference 来实现,但在大多数情况下,它会导致未定义的行为。 【参考方案1】:

const 左值引用可以绑定到任何东西。右值引用只能绑定到非const 右值。

            non-const lvalue   const lvalue   non-const rvalue   const rvalue
const T&    yes                yes            yes                yes
T&&         no                 no             yes                no

如您所见,它们非常不同。

此外,如果函数调用返回左值引用,则该表达式是左值,但如果函数调用返回对对象的右值引用,则该表达式是 xvalue。

如果结果类型是左值引用类型或对函数类型的右值引用,则函数调用是左值;如果结果类型是对对象类型的右值引用,则为 xvalue,否则为纯右值。

至于什么时候你想修改一个右值——这正是移动语义的全部意义所在。考虑以下函数调用:

void func(std::string);

func(std::string("Hello"));

表达式std::string("Hello") 是一个创建临时对象的右值。当用这个右值初始化std::string 参数时,它将选择接受右值引用的构造函数——移动构造函数。然后,此构造函数从右值中窃取内容,这通常比进行完整复制要快得多。我们可以从中窃取,因为我们知道这是暂时的。

至于什么时候应该返回const左值引用或右值引用:

当您想要授予读取“内部”对象(可能是类的成员)的访问权限但不允许人们修改它时,最常使用返回 const 左值引用。

当您希望允许调用代码从“内部”对象(可能是类的成员)移动时,最常用(根本不常见)返回右值引用。因此,它们不是从临时返回的对象移动(就像按值返回时那样),而是从内部对象移动。

这也可以通过非const 左值引用来实现,但是他们必须明确地std::move 它。

因此,您不太可能需要返回右值引用。

并不是std::forward 的返回类型类似于T&&。但是,这是具有欺骗性的,因为它可能是也可能不是右值引用,具体取决于T 的类型。见universal references。

【讨论】:

旁注:我会说程序产生const rvalues 的情况非常罕见。 谢谢。但是有没有我需要返回右值引用的实际情况? 好的,如果我理解得很好,当我将这个返回的引用传递给另一个旨在“窃取”对象的函数时,返回一个右值引用是有意义的。 @jbgs 不,返回右值引用的充分理由并不多。我会把它添加到我的帖子中。 所以如果我返回一个 const 引用,如果我将它作为参数传递给构造函数会发生什么?我猜不会选择移动构造函数。【参考方案2】:

返回前者的函数和返回后者的函数有什么实际区别吗?

这个问题似乎不正确。返回常量 lvalue-reference 的函数仅提供对对象的访问权限以供 读取,而返回 rvalue-reference 的函数提供访问权限对于 moving,这意味着调用者可以获取被引用对象的内容并将其 move 到不同的对象。它们无论如何都没有可比性。

在这两种情况下,引用必须指向一个对象,其生命周期超出返回它的函数的末尾,否则调用者将在使用该引用时出现未定义的行为。

【讨论】:

以上是关于返回 const 引用和 rvalue 引用之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

为 const 引用和 rvalue 引用编写重载

C++,在函数中采用 const lvalue 和 rvalue 引用

c ++接收const lvalue和rvalue引用参数而不重载[重复]

使用 std::move 返回时“按右值引用返回”和“按值返回”之间的区别?

C ++对非Const对象的Const引用与非Const对象的非Const引用之间的区别

模板中右值引用和 const 左值引用之间的重载