【问题标题】:What exactly happens when we use rvalue references and how does std::move work?当我们使用右值引用时究竟会发生什么以及 std::move 是如何工作的?
【发布时间】:2013-10-01 06:03:55
【问题描述】:

我正在尝试理解右值引用和移动语义。在下面的代码中,当我将 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


【解决方案1】:

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

  • 一个临时的int被创建并初始化为10

  • 那个临时的int绑定到右值引用函数参数。

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

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

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

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

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

【讨论】:

  • 那个临时变量是指无名对象?
  • @pranitkothari 我从来没有说过临时变量。它将是int类型的临时对象。是的,它将是无名的。
【解决方案2】:

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

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

其次,std::move 究竟做了什么?

它为您提供了对其参数的 rvalue 引用。它相当于(根据定义)static_cast&lt;T&amp;&amp;&gt;

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

【讨论】:

    【解决方案3】:

    std::move 通过static_cast&lt;int&amp;&amp;&gt;int&amp;&amp; 中转换int。 最终,如果类型是 classstruct,移动构造函数(如果已定义(隐式或显式))将被调用,而不是 copy constructor/classical constructor

    【讨论】:

    • 好的,我的问题得到了一半的答案..,因为我仍然不明白如果我将 value 作为 rvalue ref 传递会发生什么
    猜你喜欢
    • 1970-01-01
    • 2012-06-06
    • 2020-11-16
    • 2023-04-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2020-09-06
    • 2018-08-07
    相关资源
    最近更新 更多