正确转发右值引用的方法

Appropriate way to forward rvalue reference

本文关键字:引用 方法 转发      更新时间:2023-10-16

我有以下代码:

#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)重载。如果我想调用无效的bar(std::string&& str)过载,我要么写bar(std::move(str));要么写bar(std::forward<std::string>(str));

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

引自Effective Modern c++

从纯粹的技术角度来看,答案是肯定的:std::forward可以做到这一切。Std::move不是必需的。当然,这两个函数都不是真正必要的,因为我们可以在任何地方编写强制转换,但我希望大家都同意,那将是令人讨厌的。Std::move的优点是方便、减少出错的可能性和更清晰。

在这里使用std::move

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

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

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

  • 避免显式指定模板参数
  • 它直奔主题:std::forward不打算以这种方式使用(cfr)。通用引用)或在这种情况下,尽管它肯定会起作用

我可能同意"我转发这个右值引用到另一个函数"作为一个独立的句子可能是有意义的,但它有点错过了问题的重点。你可以重新连接你的大脑,把它想象成"继续‘移动’这个右值引用到另一个函数"

也可能相关:https://stackoverflow.com/a/18214825/1938163

当你确定它是右值引用时,你可以移动它。

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

模板代码&&平均通用引用,可以是右值,也可以是左值。

还需要注意的是,std::move是在没有任何检查的情况下强制转换它,不像forward,所以如果你不确定你应该做什么,forward更安全,move更快。