返回值的转发.需要 std::forward 吗?

我正在编写一个包含许多其他库中的函数和方法的库.为了避免处理返回值,我正在应用 std::forward ,如下所示:

I am writing library which wraps a lot of functions and methods from other library. To avoid coping of return values I am applying std::forward like so:

template<class T>
T&& wrapper(T&& t) { 
   f(t);  // t passed as lvalue  
   return std::forward<T>(t);
}

f 返回 void 并采用 T&& (或重载价值).包装器始终返回包装器的参数,并且返回值应保留参数的价值.我真的需要在 return 中使用 std::forward 吗?RVO 是否让它变得多余?它是参考(R 或 L)这一事实是否使它变得多余?如果 return 不是最后一个函数语句(在某些 if 中),是否需要它?

f returns void and takes T&& (or overloaded on valueness). Wrapper always returns wrappers's param and on returned value should preserve valuness of argument. Do I actually need to use std::forward in return? Does RVO makes it superfluous? Does the fact that it is a reference (R or L) makes it superfluous? Is it needed if return is not last function statement (inside some if)?

wrapper() 是否应该返回 voidT&& 值得商榷,因为调用者可以通过 arg (这是参考,R或L).但在我的情况下,我需要返回值,以便 wrapper() 可以在表达式中使用.

It is debatable if wrapper() should return void or T&&, because caller have access to evaluated value via arg (which is reference, R or L). But in my case I need to return value so that wrapper() can be used in expressions.

这可能与问题无关,但已知函数 f 不会从 t 窃取,因此第一次使用 std::forward<f(std::forward<T>(t)) 中的/code> 是多余的,被我删除了.

It might be irrelevant to the question, but it is known that functions f does not steal from t, so 1st use of std::forward in f(std::forward<T>(t)) is superfluous and it was removed by me.

我写过小测试:https://gist.github.com/3910503

测试表明,返回未转发的 T- 确实会在 gcc48 和 clang32 中使用 -O3 创建额外的副本(RVO 不会启动).

Test shows, that returning unforwarded T- does creates extra copy in gcc48 and clang32 with -O3 (RVO does not kicks in).

另外,我无法从 UB 获得不良行为:

Also, I was not able to get bad behavior from UB in:

auto&& tmp = wrapper(42); 

它不能证明任何原因,因为它是 undefined 行为(如果它是 UB).

It does not prove anything of cause because it is undefined behavior (if it is UB).

推荐答案

如果你知道 t 在调用 f 后不会处于移动状态,您的两个比较明智的选择是:

In the case that you do know that t will not be in a moved-from state after the call to f, your two somewhat sensible options are:

  • return std::forward<T>(t) 类型为 T&&,它避免了任何构造但允许编写例如自动&&ref = wrapper(42);,这使得 ref 成为悬空引用

  • return std::forward<T>(t) with type T&&, which avoids any construction but allows for writing e.g. auto&& ref = wrapper(42);, which leaves ref a dangling reference

return std::forward<T>(t) 类型为 T,当参数为右值时,它在最坏的情况下请求移动构造 --这避免了prvalues的上述问题,但可能会窃取xvalues

return std::forward<T>(t) with type T, which at worst requests a move construction when the parameter is an rvalue -- this avoids the above problem for prvalues but potentially steals from xvalues

在所有情况下,您都需要 std::forward.不考虑复制省略,因为 t 始终是引用.

In all cases you need std::forward. Copy elision is not considered because t is always a reference.

相关文章