当我们使用右值引用时到底会发生什么以及 std::move 是如何工作的? [重复]

问题描述 投票:0回答:3

我正在尝试理解右值引用和移动语义。在下面的代码中,当我将 10 传递给 Print 函数时,它会调用右值引用重载,这是预期的。但究竟会发生什么,这 10 会被复制到哪里(或者从它引用的地方)。其次,

std::move
实际上是做什么的?它是否从
i
中提取值 10 然后传递它?或者它指示编译器使用右值引用?

void Print(int& i)
{
    cout<<"L Value reference "<<endl;
}

void Print(int&& i)
{
    cout<<"R Value reference "<< endl;
}

int main()
{
    int i = 10;

    Print(i); //OK, understandable
    Print(10); //will 10 is not getting copied? So where it will stored

    Print(std::move(i)); //what does move exactly do

    return 0;
}

谢谢。

c++ c++11 move-semantics rvalue-reference
3个回答
9
投票

但是到底发生了什么,这 10 个将在哪里被复制(或从它引用的地方)

创建一个临时值,并将引用传递给函数。临时变量是rvalues,因此可以绑定到rvalue引用;所以选择第二个重载。

其次

std::move
实际上做了什么?

它为您提供了对其参数的rvalue引用。它相当于(根据定义)

static_cast<T&&>

尽管有这个名字,它本身并不做任何运动;它只是为您提供一个可用于移动值的参考。


9
投票

10
的情况下,可能会涉及优化,这会改变实际的实现,但从概念上讲,会发生以下情况:

  • 创建临时

    int
    并使用值
    10
    进行初始化。

  • 临时

    int
    绑定到 r 值参考函数参数。

因此从概念上讲,没有复制 - 引用将指的是临时的。

至于

std::move()
:可能存在一些与引用等相关的棘手位,但原则上,它只是到右值引用的转换。
std::move()
实际上移动任何东西。它只是将其参数转换为右值,以便可以将其移出。

无论如何,“移动”并不是一个真正定义的操作。虽然考虑移动很方便,但重要的是左值与右值的区别。

“移动”通常由移动构造函数、移动赋值运算符和采用右值引用的函数(例如

push_back()
)来实现。正是它们的实现使移动成为实际的移动 - 也就是说,它们的实现使得它们可以“窃取”r 值的资源而不是复制它们。这是因为,作为右值,它将不再可访问(或者你向编译器保证)。

这就是为什么

std::move()
启用“移动” - 它将其参数转换为右值,发出信号,“嘿,编译器,我不会再使用这个左值了,你可以让函数(例如移动向量)将其视为 r 值并从中窃取。”


-1
投票

std::move
通过
int
int&&
投射到
static_cast<int&&>
中。 最终,如果类型是
class
struct
,则将调用移动构造函数(如果已定义(隐式或显式)),而不是调用
copy constructor
/
classical constructor

© www.soinside.com 2019 - 2024. All rights reserved.