老沫白 发表于 2023-5-30 19:37:48

右值引用

std move不是返回一个右值引用吗,为什么返回值能传给一个接受右值引用的函数,右值引用本身还是左值啊

isdkz 发表于 2023-5-30 19:37:49

老沫白 发表于 2023-5-30 19:46
那为什么直接给接受右值的函数穿右值引用不行,有时看做右值

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

考虑以下代码:

int&& rvalue_ref = 5;


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

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

void accept_rvalue_ref(int&& x) {
    // 处理 x
}

int main() {
    int&& rvalue_ref = 5;
    accept_rvalue_ref(std::move(rvalue_ref));
}


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

sfqxx 发表于 2023-5-30 19:40:07

std::move 函数的返回值是一个右值引用。如果将 std::move 的返回值传递给一个接受右值引用的函数,则该函数会试图使用该参数的内容,而不是该参数本身。

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

因此,在使用 std::move 时,需要根据具体的上下文和语义来确定应该如何处理其返回值。如果需要将其传递给一个接受右值引用的函数,则可以直接将其作为函数参数传递;如果需要将其赋值给一个左值引用变量,则需要使用引用折叠或 std::forward 来保持其右值引用性质。

isdkz 发表于 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的返回值传递给接受右值引用的函数:

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

int main() {
    int a = 5;
    accept_rvalue_ref(std::move(a)); // 将 a 转为右值,并传递给函数
}


总结一下,虽然右值引用本身是左值,但你可以把它当作一个右值来使用(例如,将其传递给一个接受右值引用的函数)。只是在你这样做之后,你需要特别小心,因为这可能会破坏它的状态。

老沫白 发表于 2023-5-30 19:45:06

sfqxx 发表于 2023-5-30 19:40
std::move 函数的返回值是一个右值引用。如果将 std::move 的返回值传递给一个接受右值引用的函数,则该函 ...

那为什么直接给接受右值的函数穿右值引用不行,试图调用其内容

老沫白 发表于 2023-5-30 19:46:32

isdkz 发表于 2023-5-30 19:43
首先,我们需要理解左值、右值和右值引用的概念:

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


那为什么直接给接受右值的函数穿右值引用不行,有时看做右值

sfqxx 发表于 2023-5-30 19:58:18

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

{:10_244:}

isdkz 发表于 2023-5-30 19:59:52

sfqxx 发表于 2023-5-30 19:58


另外两个我没跟你抢{:10_256:}

sfqxx 发表于 2023-5-30 21:44:09

isdkz 发表于 2023-5-30 19:59
另外两个我没跟你抢

明天就别跟我抢了,我想上100

isdkz 发表于 2023-5-30 21:58:20

sfqxx 发表于 2023-5-30 21:44
明天就别跟我抢了,我想上100

你确定你一天可以搞到10个?

sfqxx 发表于 2023-5-30 22:02:43

isdkz 发表于 2023-5-30 21:58
你确定你一天可以搞到10个?

只要你罢工1天

老沫白 发表于 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++官方给出的标准

isdkz 发表于 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
页: [1]
查看完整版本: 右值引用