返回值的转发.需要 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() 是否应该返回 void 或 T&& 值得商榷,因为调用者可以通过 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 typeT&&, which avoids any construction but allows for writing e.g.auto&& ref = wrapper(42);, which leavesrefa 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.
相关文章