6

我试图理解右值引用和移动语义。在下面的代码中,当我将 10 传递给 Print 函数时,它会调用右值引用重载,这是预期的。但是到底发生了什么,这 10 个将被复制到哪里(或从哪里引用)。其次,std::move实际上做什么?它是否从中提取值 10i然后传递它?或者是编译器使用右值引用的指令?

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;
}

谢谢。

4

3 回答 3

9

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

  • 临时int创建并使用 value 初始化10

  • 该临时int值绑定到 r 值参考函数参数。

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

至于std::move():可能有一些与引用等相关的棘手位,但主要是,它只是对 r 值引用的强制转换。实际上std::move()没有移动任何东西。它只是将其参数转换为 r 值,以便可以将其移出。

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

“移动”通常由移动构造函数、移动赋值运算符和采用右值引用的函数(例如push_back())实现。正是它们的实现使移动成为实际的移动——也就是说,它们的实现是为了“窃取” r-value 的资源而不是复制它们。那是因为,作为一个 r 值,它将不再可访问(或者您向编译器保证)。

这就是std::move()启用“移动”的原因——它将它的参数变成一个右值,发出信号,“嘿,编译器,我不会再使用这个左值了,你可以让函数(比如移动 ctors)把它当作一个r 值并从中窃取。”

于 2013-10-01T06:17:39.260 回答
8

但是到底会发生什么,这 10 个将被复制到哪里(或从哪里引用)

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

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

它为您提供了对其参数的右值引用。它(根据定义)等同于static_cast<T&&>.

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

于 2013-10-01T06:45:18.120 回答
-1

std::move通过. int_ int&&_ static_cast<int&&>最终,如果类型是 aclass或 a struct,则移动构造函数(如果已定义(隐式或显式))将被调用而不是copy constructor/ classical constructor

于 2013-10-01T06:13:40.183 回答