之前我已经向你介绍了C++中的std::move,它的作用是无论你传给它的是左值还是右值,通过std::move之后都变成了右值。而今天我们要介绍的std::forward则与之不同,它的作用是什么呢?
forward的作用
std::forward被称为完美转发,它的作用是保持原来的值
属性不变。啥意思呢?通俗的讲就是,如果原来的值是左值,经std::forward处理后该值还是左值;如果原来的值是右值,经std::forward处理后它还是右值。
看看下面的例子,你应该就清楚上面这句话的含义了:
1 |
|
在上面的代码中,定义了两个模板函数,一个接收左值,另一个接收右值。在testForward
函数中向模板函数print
传入不同的参数,这样我们就可以观察出forward与move的区别了。
上面代码执行结果如下:
1 | lvalue |
从上面第一组的结果我们可以看到,传入的1虽然是右值,但经过函数传参之后它变成了左值(在内存中分配了空间);而第二行由于使用了std::forward函数,所以不会改变它的右值属性,因此会调用参数为右值引用的print模板函数;第三行,因为std::move会将传入的参数强制转成右值,所以结果一定是右值。
再来看看第二组结果。因为x变量是左值,所以第一行一定是左值;第二行使用forward处理,它依然会让其保持左值,所以第二也是左值;最后一行使用move函数,因此一定是右值。
通过上面的例子我想你应该已经清楚forward的作用是什么了吧?
forward实现原理
要分析forward实现原理,我们首先来看一下forward代码实现。由于我们之前已经有了分析std::move的基础,所以再来看forward代码应该不会太困难。
1 | template <typename T> |
forward实现了两个模板函数,一个接收左值,另一个接收右值。在上面有代码中:
1 | typename std::remove_reference<T>::type |
的含义我们在分析std::move时已经向你做了说细的说明,其作用就是获得去掉引用后的参数类型。所以在上面的两上模板函数中,第一个是左值引用模板函数,第二个是右值引用模板函数。
紧接着forward模板函数对传入的参数进行强制转换,转换的目标类型符合引用折叠规则,因此左值参数最终转换后仍为左值,右值参数最终转成右值。
小结
本文我们首先通一个小例子向你介绍了std::forward的作用为“完美转发”,也就是不改变原值的属性。接着我带你分析了std::forward的原码实现,如果你看过我之前对std::move的分析文章,相信你在阅读std:forward的代码实现时不会遇到什么困难。