c++11学习笔记(5)- 引用折叠和完美转发

C++通过引入一条所谓“引用折叠”的语言规则,并结合模板推导来完成完美转发的。
首先看一个例子:

当我们给函数传入引用时,如果我们对函数 testFunc 传入一个非引用类型的数据,那么形参中r的类型时什么呢?传入一个右值引用,形参r中的类型是什么呢?如果函数参数声明的类型是右值引用,传入左值引用结果又会怎样呢?

模板对类型的推到规则和简单,当转发函数的实参是类型T的左值引用,那么模板参数被推导为T&类型;如果转发函数的实参是类型T的右值引用,那么模板参数被推导为T&&类型。
具体引用折叠可以参照下表:

函数参数声明的类型 传入实参的类型 r的类型
T& TR r&
T& TR& r&
T& TR&& r&
T&& TR r&&
T&& TR& r&
T&& TR&& r&&

从上表可以看出无论传入什么类型,右值引用都可以保持跟出入的实参类型保持不变。
所以,我们可以这么写完美转发的模板:

  • 当传入的为一个const T类型实参时,如果不适用右值引用,则需要声明一个const T的函数版本,因为const T&无法转换为T&,由于使用的右值引用我们就可以完全不用声明带有const版本的转发函数。
  • 使用std::forward是为了保证函数可以调用正确形参形式的函数。

下面是一个不带std::forward的示例:

函数的运行结果为:
func(int& t)
func(const int& t)
func(int& t)

但是我们想让调用函数 perfectForward(10); 的时候调用函数 void func(const int&& t) 因为std::move(a)是一个右值引用。而由于引用折叠的作用,当传入一个右值到形参 T& 中会被认为推导为左值。因此,需要是使用std::forwardstd::forward的作用就是强制转化为实际类型的值作为形参。
更改为std::forward 后,运行效果为:
func(int& t)
func(const int& t)
func(const int&& t)

You May Also Like

About the Author: admin

喜欢编程、爱游戏,更爱生活。

发表评论

电子邮件地址不会被公开。