【问题标题】:Why use std::forward rather than std::move for data member in rvalue reference constructor's initialization list?为什么在右值引用构造函数的初始化列表中使用 std::forward 而不是 std::move 作为数据成员?
【发布时间】:2017-11-03 11:58:14
【问题描述】:

我已经阅读了这些材料:

What's the difference between std::move and std::forward

std::move Vs std::forward

this answer 非常接近我的问题,但一个是setImage,另一个是右值引用构造函数,所以恐怕存在一些微妙的东西。

转发

class ClassRoom
{
private:
    vector<string> students;

public:
    ClassRoom(vector<string>&& theStudents)
        :students{std::forward<vector<string>>(theStudents)}
    {
    }
}

移动

class ClassRoom
{
private:
    vector<string> students;

public:
    ClassRoom(vector<string>&& theStudents)
        :students{std::move(theStudents)}
    {
    }
}

有人告诉我forward 是正确的方法,因为forward 的用途之一是将右值引用变量传递给其他人并保证不再使用它。但我不知道为什么不在这里使用move,他说的对吗?

【问题讨论】:

  • 答案是:不要。当您想完善前推推导参数(模板/自动)时,使用std::forward - 这可能等效于std::move(当推导参数是右值引用时)。当你想离开时使用std::move

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


【解决方案1】:

在这个例子中,std::movestd::forward 做同样的事情。

如果将示例更改为推导类型,则情况不同,例如

template<typename Arg>
ClassRoom(Arg&& theStudents)
    :students{std::forward<Arg>(theStudents)}
{
}  

v.s.

template<typename Arg>
ClassRoom(Arg&& theStudents)
    :students{std::move(theStudents)}
{
}

然后:

vector<string> local_students = /* ... */;
ClassRoom cr(local_students) 

Arg 推导出为vector&lt;string&gt;&amp;,这意味着不同的事情发生

转发:

forward&lt;vector&lt;string&gt;&amp;&gt; 传递左值引用,因此选择的vector::vector 的重载是复制构造函数,local_students 不受影响

移动:

move&lt;vector&lt;string&gt;&amp;&gt; 将左值引用转换为右值引用,因此选择的vector::vector 的重载是移动构造函数,local_students 现在处于移动状态

【讨论】:

  • 这里真的需要可变参数模板吗?
  • 这是传播vector::vector的所有不同arities的合理示例
  • 这个例子太过分了,因为它是基于原始的只有一个参数的,所以可能会让读者误以为std::forward只有可变参数模板才有意义
  • @Gruffalo:这是一个有效的评论。当我学习这些东西时,我犯了这个错误。
【解决方案2】:

我会在这里使用std::movestd::forward 旨在转发通用引用。在这种情况下没有通用参考。 尽管在此示例中没有区别,但std::move 更简洁且更自我记录。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-10-19
    • 1970-01-01
    • 2018-01-13
    • 1970-01-01
    • 2020-10-28
    • 2015-08-28
    • 2016-03-26
    相关资源
    最近更新 更多