Leo*_*sky 31 c++ return rvalue-reference perfect-forwarding c++11
我正在编写从其他库中包含很多功能和方法的库.为了避免复制返回值我正在这样应用std::forward:
template<class T>
T&& wrapper(T&& t) {
f(t); // t passed as lvalue
return std::forward<T>(t);
}
Run Code Online (Sandbox Code Playgroud)
f返回void并获取T&&(或超载值).包装器总是返回包装器的参数,返回值应该保留参数的值.我是不是真的需要使用std::forward的return?RVO会让它变得多余吗?它是参考(R或L)的事实是否是多余的?如果return不是最后一个函数语句(在some if中),是否需要它?
如果wrapper()应该返回void或者是有争议的T&&,因为调用者可以通过arg访问评估值(参考,R或L).但在我的情况下,我需要返回值,以便wrapper()可以在表达式中使用.
它可能与这个问题无关,但众所周知,函数f不会被窃取t,所以第一次使用std::forwardin f(std::forward<T>(t))是多余的,它被我删除了.
我写过小测试:https://gist.github.com/3910503
测试显示,返回未转发T- 确实在gcc48和clang32中创建了额外的副本与-O3(RVO没有启动).
此外,我无法从UB中获得不良行为:
auto&& tmp = wrapper(42);
Run Code Online (Sandbox Code Playgroud)
它没有证明任何原因,因为它是未定义的行为(如果它是UB).
如果你确实知道t在通话后不会处于移动状态f,你的两个有些明智的选择是:
返回std::forward<T>(t)类型T&&,这避免了任何结构,但允许写,例如auto&& ref = wrapper(42);,留下ref悬挂参考
返回std::forward<T>(t)类型T,最好在参数为右值时请求移动构造 - 这避免了prvalues的上述问题,但可能从xvalues窃取
在你需要的所有情况下std::forward.不考虑复制省略因为t始终是参考.
根据此函数传递的内容,它会导致未定义的行为!更准确地说,如果将非左值(即右值)传递给此函数,则返回引用引用的值将过时.
也T&&并不是一个"通用参考"虽然效果有点像在通用参考T可以推断为T& 或T const&.有问题的情况是当它被推断为T:参数在函数返回之后作为临时传递而死,但在任何东西都可以获得对它的引用之前.
std::forward<T>(x)在调用另一个函数时,使用仅限于转发对象:作为临时函数进入的函数中的左值.使用std::forward<T>(x)let x看起来像一个临时的,如果它作为一个 - 因此,允许从x创建被调用函数的参数时移动.
当您从函数返回一个对象时,您可能需要处理几个场景,但它们都不涉及std::forward():
const或非引用,const您不希望对该对象执行任何操作,只返回引用.return语句都使用相同的变量或者所有语句都使用临时变量,则可以使用复制/移动省略,并将用于正常的编译器.由于复制/移动省略是一种优化,因此不一定会发生.std::move()允许从本地对象移动.在大多数情况下,生成的类型是T,你应该返回T而不是T&&.如果T是左值类型,则结果可能不是左值类型,并且可能需要从返回类型中删除引用限定.在您特别询问类型T工作的方案中.