【问题标题】:Move semantics with std::vector misunderstanding when passing to a function传递给函数时使用 std::vector 误解移动语义
【发布时间】:2021-04-22 02:43:00
【问题描述】:

我尝试理解移动语义的概念并做了一些测试。我有以下功能:

// testing the move semantic when passing 
// argument to be modified without copying

void process_copy( std::vector<int>&& aVec)
{
    std::cout << "Move semantic\n";
    aVec.push_back(42);
}

现在在 main 函数中,如下:

int main()
{
    std::vector<int> w_vec = {1,2,3,4,5};
    process_copy( std::move(w_vec));
}

我希望w_vec 现在是空的,因为我通过移动转换(将左值转换为右值)传递了它。但结果是w_vec 现在包含 6 个元素(42 已添加到向量中)。

我想念什么? std::vector是可移动的对象吗?

【问题讨论】:

  • std::move() 只是强制转换。你必须将结果传递给将要移动的东西,如果你想被移动,而不仅仅是演员......让我找到许多重复项之一。
  • 这能回答你的问题吗? What is std::move(), and when should it be used?
  • "要修改的参数而不复制" - 所以只需传递一个普通的引用 &amp; vec,而不是一个右值引用 &amp;&amp; vec。然后您不必使用std::move() 来转换为右值引用。移动语义似乎并不意味着您认为它们的意思,并且单独的 std::move() 永远不会移动,只需转换为右值 ref 以便接收器可能从相同移动。
  • 正如你的标题所说,它是语义。没有调用执行移动的代码,因此没有发生移动。

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


【解决方案1】:

我的 CoreCpp 2019 T 恤的图片可能与此处相关。

这是前面。

有趣的是std::move 的这种行为有点令人惊讶even for Howard Hinnant himself,右值和移动语义背后的人。但是他得到了一个非常彻底的答案there。

【讨论】:

  • 我认为可以肯定地说,我从未对我设计的行为感到惊讶。自我回答是approved technique for disseminating knowledge。
  • @HowardHinnant 这是个玩笑。我偶尔也会使用回答我自己问题的技巧。希望这不是一个冒犯的笑话,如果是的话,我当然可以编辑以改写或删除它。无论如何,如果我发布的 T 恤上的解释还不够,你的问题和答案是一个很好的资源。
  • 不,我一点也不生气。感谢link!
【解决方案2】:

您可能缺少的是您只是将 rvalue 引用 绑定到您传递的向量;你根本没有移动任何矢量对象。

process_copy() 参数的类型为 std::vector&lt;int&gt;&amp;&amp;,即对 std::vetor&lt;int&gt; 的右值引用:

void process_copy(std::vector<int>&& aVec)

在调用process_copy() 时使用std::move(),如下所示:

process_copy(std::move(w_vec));

您只是可以将此引用(即process_copy() 的参数aVec)绑定到参数(即向量w_vec)。也就是说,以下内容无法编译:

process_copy(w_vec);

因为您无法将右值引用 (aVec) 绑定到 左值 (w_vec)。


如果您希望在调用process_copy() 时移动向量参数w_vec,那么您可以使用函数来取而代之以std::vector&lt;int&gt; 按值 并在调用函数的时刻:

void process_copy(std::vector<int> aVec) // <-- not a reference
{
    aVec.push_back(42);
}

通过在调用此process_copy() 时用std::move() 标记向量参数,参数aVec 将被移动构造——因此向量参数最终将处于移动状态。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 2013-10-17
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-20
    相关资源
    最近更新 更多