返回值的转发.需要 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 leavesref
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.
相关文章