引用折叠和完美转发

最新学习C++11,发现引用折叠和完美转发的概念非常的不好理解。
今天发现了一篇文章,可以把这两个概念讲的特别清楚。

from:https://zhuanlan.zhihu.com/p/50816420

1、引用折叠

T& & = T&
T& && = T&
T&& & = T&
T&& && = T&&

左侧这么多连续的&在C++中的语法是不允许的,但是是在使用模板泛化编程中是会遇到的, 这个时候,编译器会自动根据上面的规则把进行转换。
有网友总结的很好:

左值引用会传染,只要有一个&,结果一定是左值引用

2、模板中的类型推断

template <class T>
void myprint(T && t)
{
	std::cout << "myprint(T &&)" << std::endl;
}

这个模板函数,可以根据输入,推断出T的类型。

这里面有一个情况必须要清楚,就是这个函数的参数的最终类型,一定是个引用

1、如果T是int型, t的类型是 int &&
2、如果T是int&型,t的类型是 int& && = int&
3、如果T是int&&型,t的类型是 int && && = int&&

总结起来,t一定是一个左值引用或者右值引用类型。

int a = 10;
myprint(a);
myprint(20);

当按照这个方式调用时,a是一个左值引用,根据前面第2条,可以推断出,T的类型是int&。

20是一个右值,根据第1条规则,编译器推断,T的类型为int。

即如果实参是左值,T被推断为实参类型的引用类型。
如果实参是右值,T被推断为实参的类型。

3、完美转发

在模板函数中会遇到的一个问题是:无论模板函数的实参是左值还是优质,在模板函数内部都有一个局部变量与之对应,此时使用这个参数调用其他函数时,它都是一个左值。 所以在这个时候,需要在模板函数内部,有一个机制,保证接收到的参数保持他们实参原来的值类型。

完美转发中,用到了一个很核心的函数std::forward。如下是它的定义

template<typename T>
T&& forward(T &param)
{
	return static_cast<T&&>(param);
}

从定义上可以看到无论T是哪种类型,根据引用折叠的规则,参数param都是一个左值引用类型。

从前面的分析我们知道

如果实参是左值,T被推断为实参类型的引用类型。
如果实参是右值,T被推断为实参的类型

当模板函数的实参是a(左值)时,T被推断为int &。根据折叠规则,带入上面的模板函数,生成的函数为:

int & forward(int &param)
{
	return static_cast<int&>(param);
}

返回的是一个左值引用。 和实参类型一致

当模板函数的实参是20(右值)时,T被推断为int 。根据折叠规则,带入上面的模板函数,生成的函数为:

int && forward(int &param)
{
	return static_cast<int&&>(param);
}

返回的是一个右值引用。和实参类型一致

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值