鱼C论坛

 找回密码
 立即注册
查看: 622|回复: 12

[已解决]右值引用

[复制链接]
发表于 2023-5-30 19:37:48 | 显示全部楼层 |阅读模式
7鱼币
std move不是返回一个右值引用吗,为什么返回值能传给一个接受右值引用的函数,右值引用本身还是左值啊
最佳答案
2023-5-30 19:37:49
老沫白 发表于 2023-5-30 19:46
那为什么直接给接受右值的函数穿右值引用不行,有时看做右值

在 C++ 中,当你拥有一个名称(如变量名)的实体,无论它是左值引用还是右值引用,编译器都将其视为左值。原因在于,当你可以通过名称访问一个实体时,你就可以再次使用它,这是左值的特性。这就是为什么右值引用在某种程度上被视为左值的原因。

考虑以下代码:

  1. int&& rvalue_ref = 5;
复制代码


在这里, rvalue_ref  是一个右值引用,但我们可以通过它的名称  rvalue_ref  多次访问它。这使得它在某种程度上被视为左值。

然而,当我们想要将其传递给接受右值引用的函数时,我们需要使用  std::move  来显式地将其转为右值:

  1. void accept_rvalue_ref(int&& x) {
  2.     // 处理 x
  3. }

  4. int main() {
  5.     int&& rvalue_ref = 5;
  6.     accept_rvalue_ref(std::move(rvalue_ref));
  7. }
复制代码


这样做的原因在于, std::move  提示编译器我们知道  rvalue_ref  是一个即将被销毁的值,并且我们想要将其视为右值。这允许我们将其传递给接受右值引用的函数,同时提醒我们在之后的代码中不再使用  rvalue_ref 。

最佳答案

查看完整内容

在 C++ 中,当你拥有一个名称(如变量名)的实体,无论它是左值引用还是右值引用,编译器都将其视为左值。原因在于,当你可以通过名称访问一个实体时,你就可以再次使用它,这是左值的特性。这就是为什么右值引用在某种程度上被视为左值的原因。 考虑以下代码: 在这里, rvalue_ref 是一个右值引用,但我们可以通过它的名称 rvalue_ref 多次访问它。这使得它在某种程度上被视为左值。 然而,当我们想要将其传递 ...
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-30 19:37:49 | 显示全部楼层    本楼为最佳答案   
老沫白 发表于 2023-5-30 19:46
那为什么直接给接受右值的函数穿右值引用不行,有时看做右值

在 C++ 中,当你拥有一个名称(如变量名)的实体,无论它是左值引用还是右值引用,编译器都将其视为左值。原因在于,当你可以通过名称访问一个实体时,你就可以再次使用它,这是左值的特性。这就是为什么右值引用在某种程度上被视为左值的原因。

考虑以下代码:

  1. int&& rvalue_ref = 5;
复制代码


在这里, rvalue_ref  是一个右值引用,但我们可以通过它的名称  rvalue_ref  多次访问它。这使得它在某种程度上被视为左值。

然而,当我们想要将其传递给接受右值引用的函数时,我们需要使用  std::move  来显式地将其转为右值:

  1. void accept_rvalue_ref(int&& x) {
  2.     // 处理 x
  3. }

  4. int main() {
  5.     int&& rvalue_ref = 5;
  6.     accept_rvalue_ref(std::move(rvalue_ref));
  7. }
复制代码


这样做的原因在于, std::move  提示编译器我们知道  rvalue_ref  是一个即将被销毁的值,并且我们想要将其视为右值。这允许我们将其传递给接受右值引用的函数,同时提醒我们在之后的代码中不再使用  rvalue_ref 。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-30 19:40:07 | 显示全部楼层
std::move 函数的返回值是一个右值引用。如果将 std::move 的返回值传递给一个接受右值引用的函数,则该函数会试图使用该参数的内容,而不是该参数本身。

需要注意的是,尽管返回值是右值引用,但在某些情况下,它仍然可以被视为左值。例如,如果将 std::move 的返回值赋值给一个左值引用变量,则该变量将成为一个左值,因为其可以被取地址。但是,如果将 std::move 的返回值作为函数参数传递给一个接受右值引用的函数,则该参数仍然被视为右值引用。

因此,在使用 std::move 时,需要根据具体的上下文和语义来确定应该如何处理其返回值。如果需要将其传递给一个接受右值引用的函数,则可以直接将其作为函数参数传递;如果需要将其赋值给一个左值引用变量,则需要使用引用折叠或 std::forward 来保持其右值引用性质。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-30 19:43:07 | 显示全部楼层
首先,我们需要理解左值、右值和右值引用的概念:

· 左值(Lvalue)是指定存储位置(内存位置)的表达式,也就是说,你可以查看或者修改存储在这个位置的数据。

· 右值(Rvalue)是不指定存储位置的表达式,这种表达式仅仅是提供一个值,不能赋值。

· 右值引用(Rvalue Reference)是 C++11 引入的新特性,用于支持移动语义和完美转发。右值引用本身是一个左值,但它会延长其所绑定的临时对象的生命周期。

然后,我们来看一下  std::move 。 std::move  是一个标准库函数,它可以将左值转为右值。但请注意, std::move  并不会移动任何东西,它只是执行类型转换。事实上,你必须非常小心地使用  std::move ,因为它可以使对象处于有效但未定义的状态。

接下来,我们要了解一下右值引用在函数参数中的行为。在 C++ 中,函数参数是右值,除非它们是以引用方式传递的。这意味着,你可以把  std::move  的返回值(一个右值)传递给一个接受右值引用的函数。

当你有一个右值引用  T&&  时,你可以将其传递给接受  T&&  参数的函数。虽然右值引用在某种意义上是左值,但当用作函数参数时,它们将其参数视为右值。

一种观点是,右值引用是一种 "将即将毁灭的左值暂时视为右值" 的方式。在你继续使用它之前,你需要确保你知道你在做什么,因为这可能会破坏它的状态。如果你有一个右值引用,你可以把它当作一个右值,但一旦你这样做,你就不能再使用它作为一个左值了。

以下是一个简单的例子,说明如何将  std::move  的返回值传递给接受右值引用的函数:

  1. void accept_rvalue_ref(int&& x) {
  2.     // x 是一个右值引用
  3. }

  4. int main() {
  5.     int a = 5;
  6.     accept_rvalue_ref(std::move(a)); // 将 a 转为右值,并传递给函数
  7. }
复制代码


总结一下,虽然右值引用本身是左值,但你可以把它当作一个右值来使用(例如,将其传递给一个接受右值引用的函数)。只是在你这样做之后,你需要特别小心,因为这可能会破坏它的状态。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-5-30 19:45:06 From FishC Mobile | 显示全部楼层
sfqxx 发表于 2023-5-30 19:40
std::move 函数的返回值是一个右值引用。如果将 std::move 的返回值传递给一个接受右值引用的函数,则该函 ...

那为什么直接给接受右值的函数穿右值引用不行,试图调用其内容
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-5-30 19:46:32 From FishC Mobile | 显示全部楼层
isdkz 发表于 2023-5-30 19:43
首先,我们需要理解左值、右值和右值引用的概念:

· 左值(Lvalue)是指定存储位置(内存位置)的表达 ...


那为什么直接给接受右值的函数穿右值引用不行,有时看做右值
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-30 19:58:18 | 显示全部楼层
isdkz 发表于 2023-5-30 19:37
在 C++ 中,当你拥有一个名称(如变量名)的实体,无论它是左值引用还是右值引用,编译器都将其视为左值 ...

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-30 19:59:52 | 显示全部楼层

另外两个我没跟你抢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-30 21:44:09 | 显示全部楼层
isdkz 发表于 2023-5-30 19:59
另外两个我没跟你抢

明天就别跟我抢了,我想上100
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-30 21:58:20 | 显示全部楼层
sfqxx 发表于 2023-5-30 21:44
明天就别跟我抢了,我想上100

你确定你一天可以搞到10个?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-5-30 22:02:43 From FishC Mobile | 显示全部楼层
isdkz 发表于 2023-5-30 21:58
你确定你一天可以搞到10个?

只要你罢工1天
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-6-5 15:55:22 | 显示全部楼层
isdkz 发表于 2023-5-30 19:37
在 C++ 中,当你拥有一个名称(如变量名)的实体,无论它是左值引用还是右值引用,编译器都将其视为左值 ...

Things that are declared as rvalue reference can be lvalues or rvalues. The distinguishing criterion is: if it has a name, then it is an lvalue. Otherwise, it is an rvalue.

也就是说,只要一个右值引用有名称,那对应的变量就是一个左值,否则,就是右值。

哥们牛逼,我想问问在哪里可以看C++官方给出的标准
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2023-6-5 16:36:45 | 显示全部楼层
老沫白 发表于 2023-6-5 15:55
Things that are declared as rvalue reference can be lvalues or rvalues. The distinguishing criteri ...

https://en.cppreference.com/w/cpp/utility/move
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-24 09:26

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表