当我们使用右值引用时,究竟会发生什么?std :: move如何工作?

时间:2013-10-01 06:03:55

标签: c++ c++11 move-semantics rvalue-reference

我试图理解rvalue引用并移动语义。在下面的代码中,当我将10传递给Print函数时,它会调用rvalue reference overload,这是预期的。但究竟发生了什么,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;
}

感谢。

3 个答案:

答案 0 :(得分:9)

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

  • 创建临时int并使用值10进行初始化。

  • 临时int绑定到r值引用函数参数。

从概念上讲,没有复制 - 引用将引用临时。

对于std::move():可能存在一些与引用等相关的棘手位,但主要是,它只是一个转换为r值引用。 std::move() 实际上移动任何内容。它只是将其参数转换为r值,以便可以从中移动。

无论如何,“移动”实际上并不是一个定义的操作。虽然考虑移动很方便,但重要的是l值与r值的区别。

“移动”通常由移动构造函数,移动赋值运算符和带有r值引用的函数(例如push_back())实现。正是他们的实现使得移动成为实际的移动 - 也就是说,它们被实现以便他们可以“窃取”r值的资源而不是复制它们。那是因为,作为一个r值,它将不再可访问(或者你承诺编译器)。

这就是std::move()启用“移动”的原因 - 它将其参数转换为r值,信号,“嘿,编译器,我不再使用这个l值,你可以让函数(如作为移动ctors)将其视为r值并从中窃取。“

答案 1 :(得分:8)

  

但究竟会发生什么,10将被复制(或从其引用的地方)

创建临时值,并将引用传递给函数。 Temporaries是 rvalues ,因此可以绑定到 rvalue 引用;所以选择了第二次过载。

  

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

它为您的参数提供 rvalue 引用。它等同于(根据定义)static_cast<T&&>

尽管有这个名字,它本身并没有任何动作;它只是为您提供了一个可用于移动值的引用。

答案 2 :(得分:-1)

std::move int通过int&&投放static_cast<int&&>。 最终,如果类型是classstruct,则调用(隐式或显式)移动构造函数将被调用,而不是copy constructor / classical constructor。< / p>