栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

泛型编程之完美转发

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

泛型编程之完美转发

首先简单介绍一下几个概念
(1)直接调用:比如从main()主函数中调用funcLast()函数,这其实就叫做直接调用。
(2)转发:从main()函数中调用funcMiddle()函数,通过funcMiddle()函数调用funcLast()函数,这就叫做转发,funcMiddle()函数被当作一个跳板函数。一般情况下跳板函数都写成一个函数模板。

template
void func(T& param) {
	cout << "传入的是左值" << endl;
}

template
void func(T&& param) {
	cout << "传入的是右值" << endl;
}

template
void funcMiddle(T&& param) {
	func(param);
}


int main()
{
	int num = 2021;
	funcMiddle(num);
	funcMiddle(2022);
	system("pause");
	return 0;
}

结果:

从运行结果可以看出不管传得是左值还是右值最终的调用了左值函数,这不是我们想要的,我们需要传左值则转发最值,传右值则转发右值。那这到底是什么原因呢?
funcMiddle()函数本身的形参是一个万能引用,它即可以接受左值也可以接受右值;第一个funcMiddle()函数调用实参是左值,所以,funcMiddle()函数中调用func()中传入的参数也应该是左值;第二个warp()函数调用实参是右值,根据引用折叠规则,funcMiddle()函数接收的参数类型是右值引用,那么为什么却调用了调用func()的左值版本了呢?这是因为在funcMiddle()函数内部,右值引用类型变为了左值,因为参数有了名称,我们也通过变量名取得变量地址。

那么问题来了,怎么保持函数调用过程中,变量类型的不变呢?这就是我们所谓的“完美转发”技术,在C++11中通过std::forward()函数来实现,这个函数要么返回一个左值,要么返回一个右值,可以说forward是c++ 11标准库提供的专门为转发而存在的函数。我们修改我们的funcMiddle()函数如下:

template
void funcMiddle(T&& param) {
	func(std::forward(param));
}

运行结果:

引用折叠(Universal Collapse)
因为完美转发(Perfect Forwarding)的概念涉及引用折叠。一个模板函数,根据定义的形参和传入的实参的类型,我们可以有下面四中组合:

左值-左值 T& & # 函数定义的形参类型是左值引用,传入的实参是左值引用
左值-右值 T& && # 函数定义的形参类型是左值引用,传入的实参是右值引用
右值-左值 T&& & # 函数定义的形参类型是右值引用,传入的实参是左值引用
右值-右值 T&& && # 函数定义的形参类型是右值引用,传入的实参是右值引用
但是C++中不允许对引用再进行引用,对于上述情况的处理有如下的规则:

所有的折叠引用最终都代表一个引用,要么是左值引用,要么是右值引用。规则是:如果任一引用为左值引用,则结果为左值引用。否则(即两个都是右值引用),结果为右值引用。

即就是前面三种情况代表的都是左值引用,而第四种代表的右值引用。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/991278.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号