为什么需要转发返回值

时间:2019-06-02 16:23:12

标签: c++ c++11 c++14 perfect-forwarding

readyMasks的{​​{3}}中,给出了以下示例:

std::forward

为什么这里需要转发返回值?在什么情况下它与以下代码不同:

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

2 个答案:

答案 0 :(得分:5)

让我们打破可能性。 T::get可以返回左值引用(是左值表达式),右值引用(是xvalue表达式)或prvalue。

forward表达式会将左值表达式转换为...左值表达式。它将xvalue转换为... xvalue。并将prvalue转换为xvalue。

对于prvalue和xvalue表达式,

关于重载解析中的参数如何绑定到参数的C ++规则相同。因此,最后两个总是调用相同的函数。

因此,外部forward无法完成任何操作。确实,更糟糕比什么都不做。为什么?

因为C ++ 17和更高版本中的prvalue保证了省略; xvalues 。如果foo按值接受参数,则附加的forward将显示不必要的临时变量,然后将其移至参数中。如果类型比int更复杂,则很有可能会失去一些性能。

因此,请勿转发将直接作为函数参数传递的返回值。如果需要将值存储在中间变量auto&&中,则需要转发该值。但是,如果您要像这样原位进行操作,那就不要。

答案 1 :(得分:3)

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

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

示例不是很好,因为已经是右值。实际上,我认为第二个重载没有什么用,除了使:

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

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