【问题标题】:Why is std::forward useless in this context为什么 std::forward 在这种情况下无用
【发布时间】:2016-03-04 03:29:49
【问题描述】:

我注意到std::forward 在这种情况下毫无用处:

void consumeObject(std::unique_ptr<Object>&& robj) {
  myvector.emplace_back(std::forward<std::unique_ptr<Object>>(robj));
}

这是为什么呢?我认为当右值引用绑定到函数参数(即我可以通过名称引用它)时,它会成为该范围内的左值,并且为了向前传递需要强制转换为右值引用(如完美转发)。

为什么它是错误的/无用的?

【问题讨论】:

  • “转换为右值引用”不是“完美转发”。它在移动
  • 另外:完美转发涉及到“万能引用”,你没有万能引用;你有一个右值参考。 std::move 在这里就足够了。
  • @Dean 不,实现方式不同。 std::move 旨在在没有明确指定的模板参数的情况下使用,如果你指定它会发生什么并不是很明显。 std::forward 是故意设计的,因此它需要一个显式的模板参数。
  • @Simple,它被称为forwarding reference,不是通用引用,请使用新的和批准的名称。
  • @Dean, std::move 总是转换为右值引用,但std::forward&lt;T&gt; 有时转换为左值引用,有时转换为右值引用,具体取决于模板参数T。这个区别很重要! std::move 的全部意义在于转换为右值。 std::forward 的重点是在绑定转发引用之前转换回对象的原始值类别。所以他们不会做同样的事情。

标签: c++


【解决方案1】:

在此处(本身)使用std::forward 并没有错误,但这是不恰当的,因此会产生误导(从这个意义上说,你可以说它实际上是错了)。

您拼写“将某些内容转换为对其类型的右值引用”的方式是std::move。这是std::move 所做的唯一 事情——它是static_cast&lt;T&amp;&amp;&gt;,您不必拼出T

std::forward 是一个不同的野兽,旨在与完美转发一起使用。完美转发只发生在模板中,转发引用是可能的。转发引用是一种引用,由于语言中的特殊规则,它可以推断为左值引用或右值引用。在那里,您需要std::forward&lt;T&gt; 来恢复适当的值类别(左值或右值)。​​

玩具示例:

void print(int &)
{
  std::cout << "Lvalue\n";
}

void print(int &&)
{
  std::cout << "Rvalue\n";
}

template <class T>
void perfectForwarder(T &&v)
{
  print(std::forward<T>(v));
}

int main()
{
  int i;
  perfectForwarder(i);
  perfectForwarder(std::move(i));
  perfectForwarder(42);
}

输出将是:

左值
右值
右值

[Live]

【讨论】:

  • 我会说std::forward在这里肯定是错误的,就像不可读的代码无论是否有效都是错误的一样。
  • 谢谢!现在我明白了!
  • 我不会说这是“不必要的”。它相当误导(对读者)。
  • 这里最好详细说明一下什么是完美转发,这会将右值限制为左值,这将导致编译时错误。
  • @g24l 完美转发本身与编译时错误几乎没有关系。实际上,在我的玩具示例中,省略 std::forward不会导致错误。正如答案所述,std::forward 所做的只是“重新设置适当的值类别”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-07-29
  • 1970-01-01
相关资源
最近更新 更多