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***类型的函数,由于实参形参类型一致,所以能够直接调用构造函数,构造新链表。构造完后,就执行尾插。

总结:
相关推荐
yoothey1 小时前
报废审批流规则引擎设计——责任链模式完整实现
linux·开发语言·bash
geovindu1 小时前
python: Functional Options Pattern
开发语言·后端·python·设计模式·惯用法模式·函数式选项模式
wuyk5551 小时前
24. C 语言模块化:不是拆几个.c 文件那么简单
c语言·开发语言·stm32·单片机
凯瑟琳.奥古斯特2 小时前
K次取反最大化数组和解法(力扣1005)
开发语言·c++·算法·leetcode·职场和发展
林中青木2 小时前
CT重构原理及C++代码实现
c++·计算机视觉·重构
AC赳赳老秦2 小时前
防火墙规则批量配置实战:OpenClaw 自动生成模板、批量下发与合规性校验全解析
java·开发语言·人工智能·python·github·php·openclaw
满天星83035772 小时前
Protobuf的介绍及使用
c++
☆cwlulu2 小时前
调试排查工具介绍(gdb、strace、Valgrind等)
开发语言·c++·嵌入式硬件·ubuntu
卷无止境3 小时前
C++ 存储类说明符(Storage Class Specifier)大横评
c++·后端
卷无止境3 小时前
C++ 编程的一大坑:非常量全局变量是"万恶之源"
c++·后端