【C++11】可变参数模板

news2024/12/23 18:04:43

目录

可变参数模板

函数递归展开参数包

逗号表达式展开参数包

emplace_back


可变参数模板

其实C语言中我们就一直在使用可变参数列表。

C++11 的新特性可变参数模板能够让我们创建可变参数的函数模板和类模板,相比C++98和C++03,类模板和函数模板中只能传入固定数量的模板参数,可变模板参数无疑是一个巨大的改进。

然而可变模板参数比较抽象,使用起来需要一定技巧,现阶段我们掌握一些基础的可变参数模板特性就够了。

下面就是一个基本的可变参数的函数模板:

// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... args)
{}

那我们可变参数模板传参的形式就是这样的:

上面的参数 args 前面有省略号,所以它是一个可变参数模板,我们把带省略号的参数称为"参数包",它里面包含了0至N(N>=0)个模板参数。我们无法直接获取参数包args中的每个参数,只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模板参数的一个主要特点,也是最大的难点。

那我们使用模板参数包如何取出参数呢?

函数递归展开参数包

我们可以使用 sizeof 得出参数包中的参数个数:

注意,这里不要想当然使用for循环取参数,因为语法不支持使用args[i]的方式获取可变参数。

方法如下:

        再多添加一个模板参数 T ,然后取出 T 的数据,将参数包作为参数递归调用ShowList,这样每次都能取出参数包中的第一个参数,然后我们再编写一个空参数的ShowList,用于当参数包中没有参数时,进行递归的终止。

代码如下:

那如果这里我只有一个参数包,没有额外的模板 T,那应该咋展开呢?

逗号表达式展开参数包

这种展开参数包的方式,不需要通过递归终止函数,是直接再 expand函数体中展开的,PrintArg不是一个递归终止函数,只是一个处理参数包中每一个参数的函数。这种就地展开参数包的方式实现的关键是逗号表达式。我们知道逗号表达式会按顺序执行逗号前面的表达式

这种写法中的逗号表达式:(PrintArg(args,0)),先执行ParintArg(args),再得到逗号表达式的结果0。同时还用到了C++11中另外一个特性——初始化列表,通过初始化列表来初始化一个变长数组,{(ParintArg(args),0)...}将会展开成(ParintArg(args1),0)、(ParintArg(args2),0)、(ParintArg(args3),0)……最终会创建一个元素值都为0的数组 int arr[sizeof...(Args)]。由于是逗号表达式,再创建数组的过程中会先执行逗号表达式前面的部分PrintArg(Args)打印出参数,也就是说在构造 int 数组的过程中就将参数包展开了,这个数组的目的纯粹是为了在数组构造的过程中展开参数包。

写法如下:

还可以进行简化,不使用逗号表达式。

因为数组a是使用参数包进行构造的,我们直接让参数包调用PrintArg函数,然后函数的返回值设置为0,用于数组的初始化,也可以完成该效果。

如果想打印参数的类型,直接使用typeid(x).name()即可。

逗号表达式这种写法了解一下就行了,一般不会使用到。

emplace_back

 接下来我们看 vector 中的emplace_back接口。

 如果vector中存放的是 int,emplace_back 和 push_back 是没有任何区别的。

那如果存放的是pair这种类型, 

emplace_back插入则不用调用make_pair或初始化列表构造pair对象

我们来分析push_back和emplace_back两者的效率:

push_back插入需要调用make_pair或初始化列表构造pair对象,然后使用拷贝构造或移动构造

而emplace_back直接传入pair的参数包,当插入pair类型时,其底层就直接调用了一次构造便完成了数据的插入,

这也就是说为什么有些场景下emplace_back比push_back更加高效的原因。

接下来我们写一个Date类来测试:

class Date
{
public:
    Date(int year = 1, int month = 1, int day = 1)
        : _year(year), _month(month), _day(day)
    {
        cout << "Date(int year = 1, int month = 1, int day = 1)" << endl;
    }

    Date(const Date &d)
        : _year(d._year), _month(d._month), _day(d._day)
    {
        cout << "Date(const Date& d)" << endl;
    }

    Date &operator=(const Date &d)
    {
        cout << "Date& operator=(const Date& d))" << endl;
        return *this;
    }
private:
    int _year;
    int _month;
    int _day;
};

int main()
{
    list<Date> lt1;
    lt1.push_back(Date(2022, 11, 16));

    cout << "---------------------------------" << endl;
    lt1.emplace_back(2022, 11, 16);

    return 0;
}

测试环境为gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC),因为编译器和编译器版本的不同,底层vector实现会不同。

结果(push_back调用了构造和拷贝构造,emplace_back调用了一次构造):

使用 list 同样可以完成该测试。

emplace函数:

 emplace和emplace的区别就相当于push_back和insert的区别,即可以在指定位置进行插入。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/197405.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

19《Protein Actions Principles and Modeling》-《蛋白质作用原理和建模》中文分享

《Protein Actions Principles and Modeling》-《蛋白质作用原理和建模》 本人能力有限&#xff0c;如果错误欢迎批评指正。 第四章&#xff1a;Protein Binding Leads to Biological Actions &#xff08;蛋白质的结合会产生生物作用&#xff09; -布朗棘轮在耦合结合的过…

独角兽大牛纯手肛出的一份多线程实战文档,莫把它丢进收藏夹吃灰

为什么用多线程&#xff1f; 在操作系统级别上&#xff0c;程序的执行都是以进程为单位&#xff0c;而每一个进程中通常都会有多个线程线程互不影响地并发执行&#xff0c;那么为什么要使用多线程呢&#xff1f;其实&#xff0c;多线程的使用为程序研发带来了巨大的便利&#…

删除重复数字的三种方法(详解)

前言&#xff1a;本期是关于去重数字的三种方法详解&#xff0c;今天你c了吗&#xff1f; 输入描述&#xff1a; 第一行&#xff0c;输入一个整数n&#xff0c;表示序列有n个整数。 第二行输入n个整数&#xff08;每个整数大于等于1&#xff0c;小于等于1000&#xff09;&…

关于模板字面量,我有点好奇它的内部结构

前言 最近翻看源码的时候&#xff0c;发现一些有趣的 JS 的知识点&#xff0c;基于日常的开发经验&#xff0c;我做了一些联想和对比。整个过程充满了乐趣。 于是我想&#xff0c;是不是可以延续这种创意带来的学习的乐趣。 带的富含创造力夜晚的 buff&#xff0c;确实让我拥…

一、系统编程常用api

一、文件io文件io是linux系统提供的接口&#xff0c;针对文件和磁盘进行操作&#xff0c;不带缓存机制标准io是c语言函数库里的标准io模型&#xff0c;在stdio.h中定义&#xff0c;通过缓冲区操作文件&#xff0c;带有缓存机制标准 IO 和文件 IO 的区别如下图所示&#xff1a;文…

SSD(固态) VS HDD(机械),购买指南

大多数人买电脑的时候纠结买固态硬盘&#xff08;SSD&#xff09;还是机械硬盘(HDD)。哪个是最佳选择呢&#xff0c;是固态硬盘还是机械硬盘呢&#xff1f;这个问题没有直接的答案&#xff0c;每个购买者有不同的需求&#xff0c; 需要根据需求做选择。这些需求像是性能、和预算…

DS18B20测量温度液晶1602显示

DS18B20温度传感器简介DS18B20是一种数字温度传感器。它输出的是数字信号&#xff0c;同时具有体积小&#xff0c;硬件资源耗费少&#xff0c;抗干扰能力强&#xff0c;精度高等特点。DS18B20温度传感器特点1、单线接口&#xff1a;DS18B20仅需一条线可实现与微处理器双向通信。…

泰山服务器板载 HNS3 网卡绑核无法充分利用 CPU 的解决思路

文章目录前言解决方案排查过程应用程序运行环境与方式检查是否存在 irqbalance 进程检查中断号对应的 CPU 亲和尝试其他绑核方式尝试调整队列数量:核心数量为 2:1前言 前段时间在泰山服务器上进行性能测试&#xff0c;预期是应用进程能够占满机器大部分 CPU。但实际上&#xf…

书城第二阶段——用户注册和登陆

目录0.0 JavaEE 项目的三层架构0.1 项目阶段二&#xff1a;用户注册和登陆的实现。1、先创建书城需要的数据库和表。2、编写数据库表对应的JavaBean对象。3、编写工具类 JdbcUtils3.1、导入需要的 jar 包&#xff08;数据库和连接池需要&#xff09;&#xff1a;3.2、在 src 源…

钉钉一键登录第三方网站

钉钉一键登录第三方网站序钉钉开发者后台H5微应用应用代码开发登录页面login.html登录实现LoginController.javapom.xml增加一键登录效果展示序 企业内部系统已经做过了钉钉扫码登录&#xff0c;现在需要添加钉钉一键登录第三方网站功能&#xff0c;这里主要记录一键登录整个实…

物联网终端设备的工作原理和功能讲解

物联网终端设备是实现数据采集和数据传输的设备&#xff0c;它连接了传感网络层和传输网络层&#xff0c;起到了数据采集、数据处理、数据加密和传输的功能。 物联网终端设备由传感器、外部传感接口、CPU和外部通讯组成&#xff0c;工作原理是通过外部传感接口与传感设备连接&a…

和平精英军需精打细算天花板,330拿下一整套军需

和平精英军需精打细算天花板&#xff0c;330拿下一整套军需&#xff01; #和平精英 #这游戏不花钱 #游戏凡星计划 军需精打细算天花板&#xff0c;一个月时间花 110 块获得 436 个军需币。拿个新军需的副套问题不大。要知道和平小店的暖弄大礼包&#xff0c; 100 左右&#…

一次在 classpath 使用通配符导致的偶发问题排查与建议

说起 Classpath&#xff0c;使用 Java 的同学应该都不会陌生。不过&#xff0c;目前的项目基本都会使用 Maven 等构建工具管理&#xff0c;开发过程中也会使用高度智能化的 IDE&#xff0c;在日常使用中直接涉及 Classpath 操作可能不多。前段时间遇到一个跟 Classpath 相关的偶…

【My Electronic Notes系列——触发器】

目录 序言&#xff1a; &#x1f3c6;&#x1f3c6;人生在世&#xff0c;成功并非易事&#xff0c;他需要破茧而出的决心&#xff0c;他需要永不放弃的信念&#xff0c;他需要水滴石穿的坚持&#xff0c;他需要自强不息的勇气&#xff0c;他需要无畏无惧的凛然。要想成功&…

【栈】单调栈详情介绍及其运用

单调栈单调栈的概述&#xff08;Overview&#xff09;何时使用单调栈模拟单调递增栈单调栈的运用&#xff08;算法练习题&#xff09;模板【练习一、单调栈】739. 每日温度【练习二、单调栈哈希表】496. 下一个更大元素 I【练习三、单调栈循环数组】503. 下一个更大元素 II【练…

Word处理控件Aspose.Words功能演示:使用 C++ 处理 Word 文档中的目录

Aspose API支持流行文件格式处理&#xff0c;并允许将各类文档导出或转换为固定布局文件格式和最常用的图像/多媒体格式。 Aspose.words是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作任务。API支持生成&#xff0c;修改&#xff0c;转换&#xff0c;呈现和…

4EVERLAND IPFS CID部署,一键部署Uniswap

近日&#xff0c;4EVERLAND推出IPFS CID部署&#xff0c;开发者可以复制IPFS CID&#xff0c;一键部署到4EVERLAND。 一键部署&#xff0c;无需通过Github Repo&#xff0c;只需要知道CID即可。一键跨平台部署项目到 Arweave 或 ICP。了解IPFS CID&#xff0c;通过4EVERLAND绑…

漫谈广告机制设计 | 开篇语

很久没有写文章了&#xff0c;oCPC实践录的专栏还没有写完&#xff0c;我就换工作了&#xff0c;去了M公司&#xff0c;做的内容与oCPC不怎么相关&#xff0c;对于其中的问题思考也没有那么多了&#xff0c;好在专栏的核心思想已经基本阐明了。在M公司也已经快两年了&#xff0…

青龙+WxPusher实现资产推送

1.首先注册WXpusher&#xff1a; https://wxpusher.zjiecode.com/admin/login 扫码注册创建应用 确定完就会出现一个token&#xff0c;一定先复制保存起来&#xff0c;因为只显示一次&#xff0c;没存后期就只能重置了。 关闭后&#xff0c;这个页面有二维码和链接&#xff0…

CSS定位详解

文章目录定位为什么要使用定位定位的组成定位模式静态定位&#xff1a;按照标准流特性摆放&#xff0c;没有边偏移相对定位&#xff1a;元素在移动位置的时候&#xff0c;是相对于它原来的位置来说的绝对定位&#xff1a;在移动位置的时候相对与祖先元素固定定位&#xff1a;元…