转发返回值。是否需要std :: forward? [英] Forwarding of return values. Is std::forward is needed?

查看:112
本文介绍了转发返回值。是否需要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& (或超载)。包装器始终返回包装器的参数,返回值应保留参数的价值。我是否真的需要在返回中使用 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 type T&&, which avoids any construction but allows for writing e.g. auto&& ref = wrapper(42);, which leaves ref 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆