为什么需要转发 return 值

Why forwarding return value is needed

std::forwarddoc中给出了如下例子:

template<class T>
void wrapper(T&& arg)
{
    foo(forward<decltype(forward<T>(arg).get())>(forward<T>(arg).get()));
}

这里为什么需要转发return值?它与以下代码不同的情况是什么:

template<class T>
void wrapper(T&& arg)
{
    foo(forward<T>(arg).get());
}

The edit it was added in 声称这是第二次重载的示例:

template< class T >
constexpr T&& forward( typename std::remove_reference<T>::type&& t ) noexcept;

这个例子不是很好,因为它已经是一个右值。实际上我不认为第二个重载有什么用,除了 making:

std::forward<decltype(expression)>(expression);

适用于所有表达式(包括如果 expression 是右值),但 std::forward 的大多数用例仅限于 T&&auto&& 的左值。

让我们分解一下可能性。 T::get 可以 return 左值引用(左值表达式)、右值引用(无值表达式)或纯右值。

forward 表达式会将左值表达式转换为...左值表达式。它将 xvalue 转换为... xvalue。并且它会将纯右值转换为亡值。

C++ 关于参数如何在重载决议中绑定到参数的规则与 prvalue 和 xvalue 表达式相同。所以最后两个总是会调用同一个函数。

因此,外层forward什么也做不了。事实上,这比什么都不做更糟糕。为什么?

因为 C++17 及更高版本中的纯右值保证省略; xvalues 。如果 foo 按值获取参数,附加的 forward 将显示一个不必要的临时变量,然后将其移入参数中。如果类型比 int 更复杂,那么您很有可能会损失一些性能。

所以不要转发 return 您将直接作为函数参数传递的值。如果您需要将值存储在中间 auto&& 变量中,则需要转发它。但是,如果你这样做 in-situ,请不要这样做。