转发右值引用的适当方式

Appropriate way to forward rvalue reference

我有以下代码:

#include <iostream>
#include <string>

using std::cout;
using std::endl;

void bar(const std::string& str)
{
    cout << "const str - " << str << endl;
}

void bar(std::string&& str)
{
    cout << "str - " << str << endl;
}

void foo(std::string&& str)
{
    bar(str);
}


int main()
{
    foo("Hello World");
}

在上面的代码中,调用了 void bar(const std::string& str) 重载。如果我想调用 void bar(std::string&& str) 重载,我要么必须写 bar(std::move(str)); 要么 bar(std::forward<std::string>(str));

显然转发代码更长,但对我来说更有意义。我的问题是什么更常用和更喜欢。在我看来,写 bar(std::forward(str)); 是最好的解决方案,但这不是一个选择:)

引自Effective Modern C++

From a purely technical perspective, the answer is yes: std::forward can do it all. std::move isn’t necessary. Of course, neither function is really necessary, because we could write casts everywhere, but I hope we agree that that would be,well, yucky. std::move’s attractions are convenience, reduced likelihood of error, and greater clarity.

这里使用std::move

void foo(std::string&& str)
{
    bar(str);
}

将 return str 作为右值引用(这正是您要实现的目标),而使用 std::forward 将 return 作为左值引用(你不感兴趣的)或右值引用(因此在这种情况下等同于 std::move)。显然使用 none 只会继续调用 const std::string& str 一个,因为 str 是该函数中的左值。

底线:他们会做同样的事情,但使用 std::move 是首选,因为

  • 避免显式指定模板参数
  • 更地道
  • 直截了当:std::forward 不打算以这种方式使用(参见 Universal references)或在那种情况下使用,尽管它肯定会起作用

我可能同意“我正在将此右值引用转发给另一个函数”作为一个独立的句子可能有意义,但它有点忽略了问题的重点。你可以重新连接你的大脑,让它像“保持'moving'这个右值引用到另一个函数

也可能相关:

只要确定它是右值引用,就可以移动它。

当您不能确定它是右值引用还是左值引用时,应在模板代码中使用 Forward。 :)

在模板代码中&&表示通用引用,可以是右值也可以是左值。

另请注意,std::move 是在没有任何检查的情况下施放它,这与向前不同,因此如果您不确定应该做什么,向前会更安全,但移动会更快。