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

news2024/11/24 18:33:55

文章目录

  • 可变模板参数的概念
    • 递归函数方式展开参数包
  • STL容器中的empalce相关的接口函数
  • emplace 与 insert / push_back 的区别




可变模板参数的概念


可变参数模板是 C++11 引入的一种模板特性,允许定义可以接收任意数量参数的模板,广泛应用于函数和类的设计中,以实现灵活和通用的代码结构。

可变参数模板可以处理不定数量的模板参数。它的语法使用了三个点(...)来表示模板参数包。这使得你可以创建一个模板,它可以适应任意数量的类型或值。

语法形式

template<typename... Args>
void func(Args... args) {
    // 函数体
}
  • Args... 表示一个模板参数包,它可以是任意数量的类型参数。
  • args... 表示一个函数参数包,可以对应多个具体的实参。

上面的参数args前面有省略号,所以它就是一个可变模版参数,我们把带省略号的参数称为“参数包”,它里面包含了0到N(N >= 0)个模版参数。我们无法直接获取参数包args中的每个参数的,只能通过展开参数包的方式来获取参数包中的每个参数,这是使用可变模版参数的一个主要特点,也是最大的难点,即如何展开可变模版参数。由于语法不支持使用args[i]这样方式获取可变参数,所以我们的用一些奇招来一一获取参数包的值。

递归函数方式展开参数包

// 递归终止条件:没有参数的版本
void print() {
	std::cout << "End of recursion" << std::endl;
}

// 可变参数模板版本:处理多个参数
template<typename T, typename... Args>
void print(T first, Args... rest) {
	std::cout << first << " ";
	print(rest...); // 递归调用,逐个处理参数
}

int main() {
	print(1, 2, 3, "Hello", 4.5);
	return 0;
}

在这里插入图片描述

  • print() 是递归的终止条件,用于处理没有参数的情况。
  • 模板函数 print(T first, Args... rest) 通过递归调用自身来依次处理每个参数,直到只剩下一个参数。


STL容器中的empalce相关的接口函数


在 C++ 的标准模板库(STL)中,emplace 系列接口提供了一种更高效的方式将元素添加到容器中。emplace 的主要优势是,它可以直接在容器内部构造元素,避免了额外的拷贝或移动操作。因此,相比于使用 insertpush_back 这样的函数,emplace 系列接口在某些情况下更高效。(但也高效不了多少,因为移动操作的代价足够小)

https://cplusplus.com/reference/vector/vector/emplace_back/

template <class... Args>
void emplace_back (Args&&... args)

emplace 系列函数的主要作用是原地构造元素,而不是首先构造一个临时对象再复制或移动到容器中

原地构造:使用 emplace,你可以提供构造元素所需的参数,容器会直接在内部空间中构造该对象,避免了先创建对象再将其复制到容器的过程。
避免不必要的拷贝/移动:与 push_back() 等函数相比,emplace 可以减少临时对象的构造以及拷贝/移动操作,这在性能敏感的场景中很有帮助。

在这里插入图片描述
hyt::string是我自己模拟实现的一个string类,可以看到,我们使用emplace系列的接口,确实可以将移动拷贝省略掉。能提高一点效率,但其实移动构造的效率并不大,下面我分享一下我自己模拟写的emplace系列接口:

// 模拟实现list在之前的章节有提过,这里只是将原来的代码多增加一些接口的片段代码

// 这是list需要用到的节点类
template<class T>
struct __list_node
{
	__list_node(const T& val = T())
		:_data(val), _prev(nullptr), _next(nullptr)
	{}
	// 这里需要在原来的基础上需要增加一个可变模板参数模板的构造函数,方便下面使用new
	template<class ...Args>
	__list_node(Args&& ...args)
		: _data(std::forward<Args>(args)...), _prev(nullptr), _next(nullptr)
	{}


	T _data;
	__list_node* _prev;
	__list_node* _next;
};


template<class T>
struct list
{
	template<class ...Args>
	iterator emplace(iterator position, Args&&... args)
	{

		node* cur = position._node;
		node* prev = cur->_prev;
		// 函数参数包的完美转发
		node* newnode = new node(std::forward<Args>(args)...);

		prev->_next = newnode;
		newnode->_prev = prev;

		newnode->_next = cur;
		cur->_prev = newnode;

		return iterator(cur);
	}

	template<class ...Args>
	void emplace_back(Args&&... args)
	{
		// 函数参数包的完美转发
		emplace(end(), std::forward<Args>(args)...);
	}

	private:
	__list_node<T>* _head; // 指向节点类的指针
	
	// 获取节点函数,这里更新成了万能引用版的
	template<class T>
	node* get_node(T&& val = T())
	{
		node* new_node = new node(std::forward<T>(val)); // 完美转发
		new_node->_prev = new_node;
		new_node->_next = new_node;
		return new_node;
	}
}


emplace 与 insert / push_back 的区别

最后再来总结一下:何时使用 emplace
效率优先:如果添加对象时想避免额外的构造和拷贝,emplace 通常是更优的选择。
构造复杂对象:当元素的构造比较复杂时,emplace 可以让代码更简洁,直接传入构造参数即
在这里插入图片描述

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

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

相关文章

【js逆向学习】极志愿 javascript+python+rpc

JSRPC使用方式 逆向目标逆向过程逆向分析1、什么是 websocket2、websocket的原理3、总体过程3.1 环境说明3.2 python服务端代码3.3 python客户端代码 4、Sekiro-RPC4.1 执行方式4.2 客户端环境4.3 参数说明4.4 SK API4.5 python代码调试4.6 代码注入流程 逆向总结 逆向目标 网…

【STM32开发之寄存器版】(六)-通用定时器中断

一、前言 STM32定时器分类 STM32103ZET6具备8个定时器TIMx(x 1,2,...,8)。其中&#xff0c;TIM1和TIM8为高级定时器&#xff0c;TIM2-TIM6为通用定时器&#xff0c;TIM6和TIM7为基本定时器&#xff0c;本文将以TIM3通用定时器为例&#xff0c;分析STM32定时器工作的底层寄存器…

mysql读写分离的最佳实践

一. 传统的读写分离方式 在 MySQL 中实现读写分离可以通过以下几种方式来达到目的&#xff1a; 1. 主从复制 使用主从复制&#xff08;Master-Slave Replication&#xff09;是实现读写分离的常见方式。 主库&#xff1a;处理所有的写入操作&#xff08;INSERT、UPDATE、DE…

Qt+VS2019+大恒相机相机回调方式总结

一、前言 大恒驱动安装完成后&#xff0c;在安装目录有SDK调用文档&#xff0c;里面有更详细的调用介绍&#xff0c;此文档对近期做的Demo做一个回顾性总结。 二、调用流程概述 三、针对性内容介绍&#xff1a; 1. 在执行相机操作之前&#xff0c;需要先执行此代码&#xff1…

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-07

计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-07 目录 文章目录 计算机前沿技术-人工智能算法-大语言模型-最新研究进展-2024-10-07目录1. Evaluation of Large Language Models for Summarization Tasks in the Medical Domain: A Narrative Review摘要研究…

rust中async/await的使用

在Rust中&#xff0c;async/await 用于编写异步代码。它允许您以同步的方式编写异步代码&#xff0c;使得异步操作更易于理解和编写。 安装依赖&#xff1a; cargo add futures cargo add async-std 使用示例&#xff1a; 示例1&#xff1a; use async_std::task::block_o…

学习MDX

MDX&#xff08;Markdown JSX&#xff09;是一种开源的文件格式&#xff0c;它允许你在Markdown文件中使用JavaScript表达式和组件。MDX将Markdown的易用性与React组件的强大功能结合起来&#xff0c;使得你可以在编写文档、博客文章或其他内容时&#xff0c;嵌入可交互的组件…

顶会论文复现:PROVING TEST SET CONTAMINATION IN BLACK BOX LANGUAGE MODELS

文章目录 1 资料2 我的总结3 复现源码首先你需要有gpt的api接口安装&#xff1a;数据集执行指令源码 4 结果 1 资料 我复现的源码:https://github.com/Whiffe/test_set_contamination 官网源码&#xff1a;https://github.com/tatsu-lab/test_set_contamination 论文&#x…

tts(text to speech)使用 pyttsx3 实现文本转语音 - python 实现

文本转语音&#xff08;Text-to-Speech&#xff0c;TTS&#xff09;技术是一种将文本信息转换为口语输出的技术。它涉及多个学科&#xff0c;包括声学、语言学、数学信号处理技术和多媒体技术等。TTS技术能够将计算机中的文本信息转换为自然流畅的语音输出&#xff0c;广泛应用…

OJ在线评测系统 后端微服务架构 注册中心 Nacos入门到启动

注册中心 服务架构中的注册中心是一个关键组件&#xff0c;用于管理和协助微服务之间的通信。注册中心的主要职责是服务的注册和发现&#xff0c;确保各个微服务能够相互找到并进行调用。 主要功能&#xff1a; 服务注册&#xff1a;微服务在启动时&#xff0c;将自身信息&am…

OpenHarmony(鸿蒙南向开发)——标准系统方案之瑞芯微RK3566移植案例(下)

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 概述 OpenHarmony Camera驱动模型结构 HDI Implementation&#x…

【ubuntu】ubuntu20.04安装显卡驱动

1.安装 点击右下角Apply Changes。 等安装好之后&#xff0c;重启。 现在的nvidia驱动已经很好安装了&#xff0c;比早期时安装出现黑屏等情况好了很多。 2.验证 nvidia-smi

Mybatis plus快速使用

文章目录 Mybatis plus快速使用1.ORM2.mybatis plus介绍3.mybatis plus使用1.添加依赖2.配置信息3.启动类加入 MapperScan&#xff08;“填入mapper包的位置”&#xff09;4.创建user接口&#xff0c;在mapper中加入UserMapper接口5.mybatis-plus crud注解启动springboot项目ma…

基于图像的3D动物重建与生成

一、背景与目标 3D-Fauna 是一款用于基于图像和视频进行四足动物3D重建与生成的开源方案。自然界展示了复杂的相似性与多样性,该方法通过学习来自网上图片的四足动物的3D形态,能够从单张图片生成可动画化的带有纹理的3D网格模型。其最终目标是通过大量扩展现有的解决方案,实…

Ajax面试题:(第一天)

目录 1.说一下网络模型 2.在浏览器地址栏键入URL&#xff0c;按下回车之后会经历以下流程&#xff1a; 3.什么是三次握手和四次挥手&#xff1f; 4.http协议和https协议的区别 1.说一下网络模型 注&#xff1a;各层含义按自己理解即可 2.在浏览器地址栏键入URL&#xff0c;…

mybatis自定义类型处理器

mybatis自定义类型处理器 其实使用MySQL或Oracle数据库很少会遇到自定义类型处理器的情况&#xff0c;之前是因为项目中使用了PGSQL才接触到这块的&#xff0c;这里简单做一下记录 要创建一个自定义的类型处理器&#xff0c;就需要继承BaseTypeHandler类或者实现TypeHandler接…

数据结构 ——— 相交链表(链表的共节点)

题目要求 两个单链表的头节点 headA 和 headB &#xff0c;请找出并返回两个单链表相交的起始节点&#xff0c;如果两个链表不存在相交节点&#xff0c;则返回 NULL 手搓两个相交简易链表 代码演示&#xff1a; struct ListNode* a1 (struct ListNode*)malloc(sizeof(struc…

Git 分支提交同步到主干的详细教程——(包含命令行和idea操作两种方式)

文章目录 Git 分支提交同步到主干的详细教程一、Git 命令行操作1. 确保分支上的代码已提交2. 切换到主干分支3. 拉取最新的主干分支代码4. 合并分支到主干方式一&#xff1a;使用 merge 进行合并方式二&#xff1a;使用 rebase 进行合并 5. 推送合并后的代码到远程主干分支命令…

github 搭建个人导航网

最近搭建了个 个人的导航网&#xff0c;具体内容见下图&#xff0c;欢迎大家访问吖&#xff0c;点击访问 具体实现是使用 vue3 编写&#xff0c;白嫖 github 的 page 部署 首先在 github上创建一个仓库&#xff1a;name.github.io # name是你 github 的名字 然后在本地创建一…

Linux安装部署MySQL8.0加遇着问题解决

1.首先我先给个URL下载MySQL官方网站https://downloads.mysql.com/archives/community/ 2.选择Linux的红帽系统 3.接着选择红帽系统的7版本,x86 4.接着选择MySQL版本,此时我选择8.4.0,下载rpm bundle这个,下载下面这个就好 5.Windows文件上传到Linux系统 rz上传文件命令,找到…