7

什么情况下 std::forward不需要?它用于包装内部函数参数,即模板右值(即,它可以是左值或命名右值)。像:

template<class T>
void outer(T&& t) { 
    inner(std::forward<T>(t)); 
}

我猜一种情况是内部函数参数按值传递。还有其他情况吗?我在写std::begin(std::forward<Ct>(ct))Ct 是模板右值引用的地方时遇到了这个问题。

编辑关于可能的重复

如果我没记错的话,这是第三次尝试关闭这个 4 年的老问题,因为一些不懂这个问题的新手重复了这个问题。

“使用前锋的好处?” 和“什么时候不使用带有 r 值的 std::forward?” 是非常不同的问题。首先是为初学者介绍 r 值,其次是为高级 C++ 用户讨论完美转发。我是元模板库和 lambda 库的作者,他们不需要对基础知识进行详细描述。答案中的信息与其他问题非常不同。

4

3 回答 3

6

当模板参数类型包含值类别时,可以进行完美转发。(如果这句话没有意义,请花一点时间熟悉手头的问题。)

鉴于:

template <typename T>
void foo(T&& x); 

在 的体内fooT将采用U或的形式U&。前者意味着我们传递了一个右值,后者意味着我们传递了一个左值。我们可以这样转发这个事实:

template <typename T>
void foo(T&& x)
{
    bar(std::forward<T>(x));
}

将左值传递给foobar得到相同的左值。将右值传递给foobar获取右值。

如果你不能区分一个值类别,那么转发是没有用的。只有当您有一个以与上面相同的方式推导出的模板参数时,它才有用。所以是的,它在这里没有用:

template <typename T>
void foo(const T& x)
{
    // if this was called as foo(1), we're none the wiser
}
于 2012-08-21T05:47:54.307 回答
3

我正在回答我自己的问题,因为到目前为止我还没有得到满意的答案。如果我会对此进行哪怕很小的改进/补充 - 我会选择您的答案作为已接受。

如果能达到完美转发的效果,一般std::forward对内部功能是有利的。否则是多余的。

std::forward仅当以下任何一项为真时,才用于包装内部函数 arg :

  • 内部函数参数是templated-rvalue-ref(现在称为“转发引用”);
  • 内部函数具有多个重载,这些重载根据参数 r/l 值进行区分;
  • 内部函数具有多个重载,这些重载根据 const 区分左值参数;
于 2012-08-26T05:42:10.133 回答
-1

使用 std::forward (在模板化函数的形式参数上,其类型为 T&& 形式,T 是模板的类型参数):

  • 当内部函数调用是外部函数中参数的最后一次使用时,并且
  • 内部函数的可能重载可能会将参数作为右值引用,也可能不会。

基本原理是,当一个对象可能通过右值引用作为参数传递时(这是您使用 std::forward 所允许的),它的信息内容可能会被破坏。因此,只有当您确定不再使用该信息内容时,您才想这样做。

例子:

#include <utility>

template <class T> void f(T &&t);
template <class T> void g(const T &t);

template <class T>
void outer(bool f_first, T &&t)
  {
    if (f_first)
      {
        f(t);
        g(t);
      }
    else
      {
        g(t);
        f(std::forward<T>(t));
      }
  }

#include <string>

void foo(std::string s)
  {
    outer(true, s);
    outer(true, s + "x");
    outer(false, s);
    outer(false, std::move(s));
  }
于 2016-10-29T23:37:07.460 回答