转发返回值。是否需要std :: forward? [英] Forwarding of return values. Is std::forward is needed?
问题描述
我正在编写一个库,其中包含了其他库中的许多函数和方法。为了避免处理返回值,我在应用 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&
(或超载)。包装器始终返回包装器的参数,返回值应保留参数的价值。我是否真的需要在返回
中使用 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
不会从<$ c中窃取$ c> t ,因此 f(std :: forward< T>()中第一次使用
是多余的,被我删除了。 std :: forward
t))
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
-确实在带有-O3的gcc48和clang32中创建了额外的副本(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:
-
返回类型为
T&
的std :: forward< 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
返回类型为 T
的 std :: forward< T(t)
,在最坏的情况下要求移动构造当参数为右值时–可以避免上述prvalue的问题,但有可能从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.
这篇关于转发返回值。是否需要std :: forward?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!