c++数据结构之c++11(三)

一.可变参数模板

1.原理

注:引用须遵循引用折叠。用"..."指出一个模板参数或函数参数(Args)来表示一个包,这样在实例化的时候,就可以随意改变形参个数,即有0-N个参数。

可变参数模板就相当于模板的模板,有了它,就可以让编译器自动实现,生成相应参数个数的函数模板,并由这些模板结合指定数据类型,实例化出相应的函数:

2.包扩展

注:sizeof...是个操作符,可用于求可变参数模板实例化以后,参数包里参数的个数:

①.问题引入:

如果想要把实例化以后,参数包里的数据(实参)取出来,很多人想到的是这样的方法:

但这样是不支持的。

此时若要解析出参数包的内容,需要进行包扩展:

②.包扩展

玩了一波递归,让参数包第一个参数传给x,其余参数传给第二个参数包args,然后逐个逐个取参数包首参数:

但这里的递归属于编译时递归包的展开,不属于运行时的递归,运行时的递归自己调用自己,连函数参数的数量,种类都是一致的;而递归包的展开,每一层递归的参数数量是在减少的,且递归包里的参数数据类型并不相同:

3.emplace系列接口

Ⅰ.emplace_back和push_back的对比(以list为例)

Ⅰ-1形参的区别

从两个接口的形参可以看出,push_back插入的是定数量的参数,而emplace_back插入的是参数包。

Ⅰ-2使用的区别
传左值:

结果没有任何区别,emplace_back和push_back一样,先走拷贝构造,将数据用于构造新节点,然后尾插。实参是左值,push_back就去走形参是左值的重载,emplace_back通过引用折叠,实参处整个引用的性质仍旧是左值。

二者运行的结果:

传右值:

结果仍旧相同,只是传右值走的是移动构造而已。

直接传参:
解析过程:

push_back:

链表内节点类型为string,因此push_back被实例化为了string 的push_back。而此时的实参"11111111111111"是个const char* 类型的参数,所以要走一个隐式类型转换, 因此要去调用构造函数,构造一个string类型 的,内容是"11111111111111"的临时变量 。由于临时变量的属性是右值,所以在利用这个临时变量,构造新节点时,走一个移动构造。最后创建好新节点,就执行尾插。

emplace_back:

而emlace_back是根据实参类型来进行实例化的,因为该函数模板是可变参数模板,属于模板的模板,先通过list实例化为函数模板,再由实参"1111111111111" 直接推导出参数类型为const char* ,所以函数模板被实例化为了**const char***类型的函数,由于实参形参类型一致,所以能够直接调用构造函数,构造新链表。构造完后,就执行尾插。

总结:
相关推荐
布莱克60514 分钟前
C/C++ 中变量的声明与定义:区别、联系与常见误区
c语言·开发语言·c++·声明·定义
LabVIEW开发23 分钟前
LabVIEW 局部变量为何引发竞争条件?四种同步机制
开发语言·labview
benchmark_cc1 小时前
A 股、港股、美股如何建立统一的标的主数据格式?
开发语言·python·数据分析·pandas·量化交易·股票数据·quantdash
Zenova EdgeOS2 小时前
Go 工业边缘错误处理实战:用 errors 构建可追溯错误链
开发语言·数据库·golang
取名真是2 小时前
Python 算法知识点从基础到进阶
开发语言·python·算法
FRing033 小时前
vue2干货总结3(computed计算属性、watch监听器)
开发语言·前端·vue.js·vue2
Fatbobman(东坡肘子)4 小时前
快速消失的硬盘容量 -- 肘子的 Swift 周报 #160
开发语言·人工智能·redis·ios·swiftui·iphone·swift
揽星河..4 小时前
【C语言】底层程序设计
c语言·开发语言
JavaPub-rodert4 小时前
从零搭建通用管理后台:ShiyuAdmin 的 Go、React 与 RBAC 实践
开发语言·react.js·golang
沫璃染墨5 小时前
从零入门计算机网络系列(十二):HTTP长连接与会话管理详解——从Connection到Cookie与Session
linux·服务器·c++·tcp/ip·ubuntu·http·交互