C++ : 模板初阶
标题:C++ : 模板初阶
@水墨不写bug
正文开始:
C语言的问题 :
写不完的swap函数
在学习C语言时,我们有一个经常使用的函数swap函数,它可以将两个对象的值交换。
我们通常这样实现它:
void swap(int t1,int t2) {int tem = t1;t1 = t2;t2 = tem; }
这是很简单的函数。如果我们想交换其他类型的对象,就需要用到函数重载:
void swap(int t1,int t2){int tem = t1;t1 = t2;t2 = tem;} void swap(float t1, float t2){ float tem = t1;t1 = t2;t2 = tem;} void swap(double t1, double t2){ double tem = t1;t1 = t2;t2 = tem;} void swap(char t1, char t2){ char tem = t1;t1 = t2;t2 = tem;} void swap(long t1, long t2){ long tem = t1;t1 = t2;t2 = tem;} //...
但是,内置类型的指针理论上可以达到n级指针,n可以趋于无限大;除此之外,还有自定义类型。这样一来,你就会发现,类型是无法枚举的!一个swap函数需要实现一种类型的交换,那么swap函数是写不完的!
人工解决重复写同一个逻辑,仅仅是类型不同的代码是很低效的!为了解决这个问题,C++引入模板的概念:
顾名思义,模板就是模板,作用就是印出不同的东西,这个东西就是swap函数!
(一)模板简介
模板是C++相对于C的一个新的语法,他需要用到关键字template(模板),如果我们用模板来实现swap函数,就可这样写:
template <typename T>
void swap(T& t1, T& t2)
{T tem = t1;t1 = t2;t2 = tem;
}
template<typename或class 模板参数> + 模板主体 就是模板的基本形式。
要成功的调用模板函数,也需要特定的条件:
template <class T>
void swap(T& t1, T& t2)
{T tem = t1;t1 = t2;t2 = tem;
}
/*void swap(int t1,int t2){int tem = t1;t1 = t2;t2 = tem;}void swap(float t1, float t2){ float tem = t1;t1 = t2;t2 = tem;}void swap(double t1, double t2){ double tem = t1;t1 = t2;t2 = tem;}void swap(char t1, char t2){ char tem = t1;t1 = t2;t2 = tem;}void swap(long t1, long t2){ long tem = t1;t1 = t2;t2 = tem;}
*/
int main()
{int a = 1, b = 5;::swap(a, b);cout << a << " " << b << endl;return 0;
}
我们可以指定调用全局的swap模板函数,完成对象的值交换。
(1)为什么模板可行?模板的原理?
在编译时,编译器会 匹配 模板参数的类型,如上例,a,b的类型都是整形,所以编译器会根据根据函数的模板生成一份函数,这份函数仅仅将 T(模板参数 改成 匹配出的类型):
void swap(int t1,int t2) {int tem = t1;t1 = t2;t2 = tem; }
这样我们人工编写的工作量就减少了非常多,因为一个理论上模板可以生成n个函数(n可趋于无穷大)。
(2)匹配冲突
由于交换的是两个参数的值,当两个参数的类型不同时,理论上不能交换,此时编译器也会因为匹配类型冲突而报错:
如何解决这个问题:
i,再增加一个模板参数(推荐)
由于只有一个模板参数, 当推断类型既是int又是double时,一个参数就应付不过来了,所以需要再增加一个参数。两个模板参数,就可以进行两次参数类型匹配:
template <class T1,class T2> void swap(T1& t1, T2& t2) {auto tem = t1;t1 = t2;t2 = tem; }
##如果你是看了后面两种处理方式后又回来的,那么你很敏锐,发现了本例的问题,其实本例也发生了类型转换:
由于t1,t2类型不一致,所以在下面赋值时,必然发生了类型转换,可能导致精度丢失。但是这并不影响我们解决匹配冲突的方法:因为在实际应用中,我们一般不会让模板参数之间进行运算。(这仅仅是本例的场景不太好,使用多个模板来解决匹配冲突仍然是推荐的) ##
ii,强制转换到一致
只能解决一些特例,就拿下面这个函数模板来说:
template<class T> T Add(T t1,T t2) {return t1 + t2; }void test2() {int a = 1;double b = 5.6;double ret = ::Add((double)a, b);cout << ret; }
将a强制类型转换到double可以使编译器对a和b类型匹配都是double,这样是可以通过编译的,但是这样操作的结果是不稳定的。强制类型转换必然意味着精度或者符号的丢失,不到迫不得已,不要使用强制类型转换!
iii,显示实例化(不再推演参数)
只能解决一些特例,还是拿上面这个函数模板来说:
template<class T> T Add(T t1,T t2) {return t1 + t2; } void test2() {int a = 1;double b = 5.6;double ret = ::Add<double>(a, b);cout << ret; }
这也是可以通过编译的,在模板名称后面加上<参数类型>,意味着指定了生成的模板的匹配类型就是 这个指定的参数类型。由于指定了参数类型,其本质也是发生了类型转换,而类型转换是不推荐的。
总结:
解决匹配冲突的方法:
i,再增加一个模板参数(推荐)
ii,强制转换到一致
iii,显示实例化(不再推演参数)
(3)模板实例化的条件
当全局已经有一个匹配的函数时,模板就不会再生成新函数。
以这个例子来说:
void swap(double t1, double t2){ double tem = t1;t1 = t2;t2 = tem;}template <class T>
void swap(T& t1, T& t2)
{T tem = t1;t1 = t2;t2 = tem;
}
void test1()
{double a = 1;double b = 5;::swap(a, b);cout << a << " " << b << endl;
}
模板匹配的类型是double,由于全局已经有了类型是double的函数,所以编译器不会再通过函数模板再生成一份swap函数。
编译器会优先匹配最合适的模板:
template <class T1,class T2>
void swap(T1& t1, T2& t2)
{T1 tem = t1;t1 = t2;t2 = tem;
}
template <class T>
void swap(T& t1, T& t2)
{T tem = t1;t1 = t2;t2 = tem;
}
void test1()
{int a = 1;double b = 5;::swap(a, b);cout << a << " " << b << endl;
}
本例中,由于a,b两个变量的类型不同,所以编译器会优先选择两个模板参数的swap函数,而不是一个模板参数的swap。
在特殊情况也是可以编译通过的:
void swap(int t1, int t2)
{ int tem = t1; t1 = t2; t2 = tem;
}
void test1()
{int a = 1;double b = 5;::swap(a, b);cout << a << " " << b << endl;
}
总结:
1.全局有完全匹配的函数,编译器不再由模板生成函数;直接使用现成的函数。
2.如果有多个模板,编译器会选择最合适的模板来生成函数;
3.类型不匹配,没有模板,也可以编译通过,但是会发生类型转换,导致精度丢失。
其实模板远不止这些,本文仅仅是以函数模板为引子来讲解模板的语法,而模板还包括类模板,后者是实际中应用较多的。
类模板 就放 在将来为大家分享吧!
目录
(一)模板简介
(1)为什么模板可行?模板的原理?
(2)匹配冲突
i,再增加一个模板参数(推荐)
ii,强制转换到一致
iii,显示实例化(不再推演参数)
总结:
(3)模板的生成条件
总结:
~完
未经作者同意禁止转载
相关文章:

C++ : 模板初阶
标题:C : 模板初阶 水墨不写bug 正文开始: C语言的问题 : 写不完的swap函数 在学习C语言时,我们有一个经常使用的函数swap函数,它可以将两个对象的值交换。 我们通常这样实现它: void swap(int t1,int t2)…...

FFA-Net:用于单图像去雾的特征融合注意力网络
摘要 论文链接:https://arxiv.org/pdf/1911.07559v2 在这篇论文中,我们提出了一种端到端的特征融合注意力网络(FFA-Net)来直接恢复无雾图像。FFA-Net架构由三个关键组件组成: 一种新颖的特征注意力(FA&…...

网工内推 | 联通公司,云计算售前,AWS认证优先
01 联通数字科技有限公司 🔷招聘岗位:云计算售前工程师 🔷职责描述: 1.了解私有云,公有云,混合云等云计算技术知识,了解云计算行业现状及发展趋势。 2.承担区域项目售前工作支持,为…...

[Redis]Zset类型
Zset有序集合相对于字符串、列表、哈希、集合来说会有一些陌生。 它保留了集合不能有重复成员的特点,但与集合不同的是,有序集合中的每个元素都有一个唯一的浮点类型的分数(score)与之关联,着使得有序集合中的元素是可…...

【云原生】Kubernetes----Ingress对外服务
目录 引言 一、K8S对外方式 (一)NodePort 1.作用 2.弊端 3.示例 (二)externalIPs 1.作用 2.弊端 3.示例 (三)LoadBalancer 1.作用 2.弊端 (四)Ingress 二、Ingress的…...
项目管理之maven svn
管理jar包之间依赖关系 编译、打包、清理、测试等一系列构建工具 一、Maven的标志 1、每一个maven工程都有一个pom.xml maven项目坐标 <groupId>com.aaa</groupId>//项目路径 <artifactId>web</artifactId>项目名称 <version>0.0.1-SNAPS…...

Redis篇 list类型在Redis中的命令操作
list在redis基本的命令 一.基本命令1.lpush和range2.lpushx rpushx3.lpop rpop4.lindex linsert llen5.lrem6.ltrim lset7.blpop brpop 一.基本命令 list在redis中相当于数组或者顺序表. 1.lpush和range 2.lpushx rpushx 3.lpop rpop 4.lindex linsert llen 如果要插入的列表中…...

【C++课程学习】:类和对象(上)(类的基础详细讲解)
🎁个人主页:我们的五年 🔍系列专栏:C课程学习 🎉欢迎大家点赞👍评论📝收藏⭐文章 目录 🍟1.1类的引出: 🍟1.2类的结构: 🍟1.3类的…...

HTML 转义字符(escape characters)及其对应的符号(symbols)
以下是常见的 HTML 转义字符及其对应的符号,这些可以用于在 HTML 或 JSX 中避免解析错误和特殊字符的冲突: 空格 ( ): 或 引号: 单引号():'、‘、、’双引号("&#x…...
CPASSOC代码详解
加载环境 library("MASS") require(MASS) # Modern Applied Statistics with S,"S"指的是S语言,由贝尔实验室的约翰钱伯斯(John Chambers)等人开发。S语言是R语言的前身,许多R语言的语法和功能都…...

dirfuzz-web敏感目录文件扫描工具
dirfuzz介绍 dirfuzz是一款基于Python3的敏感目录文件扫描工具,借鉴了dirsearch的思路,扬长避短。在根据自身实战经验的基础上而编写的一款工具,经过断断续续几个月的测试、修改和完善。 项目地址:https://github.com/ssrc-c/di…...

计算机发展史 | 从起源到现代技术的演进
computer | Evolution from origins to modern technology 今天没有参考资料哈哈 PPT:(评论区?) 早期计算工具 算盘 -算盘是一种手动操作的计算辅助工具,起源于中国,迄今已有2600多年的历史,是…...

45-3 护网溯源 - 为什么要做溯源工作
官网:CVERC-国家计算机病毒应急处理中心 西工大遭网络攻击再曝细节!13名攻击者身份查明→ (baidu.com) 护网溯源是指通过技术手段追踪网络攻击的来源和行为,其重要性体现在以下几个方面: 安全防御:了解攻击源头可以帮助组织加强网络安全防御,及时采取措施防止攻击的再次…...

【JavaEE 进阶(二)】Spring MVC(下)
❣博主主页: 33的博客❣ ▶️文章专栏分类:JavaEE◀️ 🚚我的代码仓库: 33的代码仓库🚚 🫵🫵🫵关注我带你了解更多进阶知识 目录 1.前言2.响应2.1返回静态界面2.2返回数据2.3返回HTML代码 3.综合练习3.1计算器3.2用户登…...

光波长 深入程度
UV深入程度(UVC, UVB, UVA)https://mp.weixin.qq.com/s?__bizMzkwNTM0Njk3MA&mid2247483934&idx1&sn92d1ba67ead404e7714af11ec0526786&chksmc0f868ebf78fe1fd0610493e6f49a5d90835a20a829a900746906cda12f2fa12…...

MySQL数据库常见工具的基础使用_1
在上一篇文章中提到了对MySQL数据库进行操作的一些常见工具 mysqlcheck mysqlcheck是一个用于数据库表的检查,修复,分析和优化的一个客户端程序 分析的作用是查看表的关键字分布,能够让sql生成正确的执行计划(支持InnoDB,MyISAM,NDB)检查的作用是检查…...

C语言中指针的说明
什么是指针? 在C语言当中,我们可以将指针理解为内存当中存储的地址,就像生活当中,一个小区里面,在小区里面有很单元,每一栋单元,单元内的房间有着不同的房间号,我们可以同过几栋几单…...
webrtc vp8/9视频编解码介绍
文章目录 一、libvpx项目介绍libvpx基本概念编码器使用流程解码器使用流程示例代码:官方文档和资源二、VP8/9在WebRTC中的应用2.1 VP82.2 VP92.3如何选择哪种编码方式2.4 vp9编码的主要步骤2.5 vp9解码C++代码示例注意事项三、webrtc在音视频传输中是怎样选择vp8还是vp9<...

【机器学习300问】107、自然语言处理(NLP)领域有哪些子任务?
自然语言处理(NLP)是计算机科学、人工智能和语言学领域的一个交叉学科,致力于让计算机能够理解、解析、生成和与人类的自然语言进行互动。自然语言指的是人们日常交流使用的语言,如英语、汉语等,与计算机编程语言相对。…...

面试被问准备多久要孩子?这样回答
听说有人面试被问到多久要孩子的问题,当时觉得很尴尬,不知如何回答,怕回答的不好不被录用,其实你可以这样回答,让面试官心满意足。 A 面试官:结婚了吗? 我:结婚了 面试官࿱…...

手游刚开服就被攻击怎么办?如何防御DDoS?
开服初期是手游最脆弱的阶段,极易成为DDoS攻击的目标。一旦遭遇攻击,可能导致服务器瘫痪、玩家流失,甚至造成巨大经济损失。本文为开发者提供一套简洁有效的应急与防御方案,帮助快速应对并构建长期防护体系。 一、遭遇攻击的紧急应…...
mongodb源码分析session执行handleRequest命令find过程
mongo/transport/service_state_machine.cpp已经分析startSession创建ASIOSession过程,并且验证connection是否超过限制ASIOSession和connection是循环接受客户端命令,把数据流转换成Message,状态转变流程是:State::Created 》 St…...

MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)
本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

Razor编程中@Html的方法使用大全
文章目录 1. 基础HTML辅助方法1.1 Html.ActionLink()1.2 Html.RouteLink()1.3 Html.Display() / Html.DisplayFor()1.4 Html.Editor() / Html.EditorFor()1.5 Html.Label() / Html.LabelFor()1.6 Html.TextBox() / Html.TextBoxFor() 2. 表单相关辅助方法2.1 Html.BeginForm() …...

【Linux】自动化构建-Make/Makefile
前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具:make/makfile 1.背景 在一个工程中源文件不计其数,其按类型、功能、模块分别放在若干个目录中,mak…...

沙箱虚拟化技术虚拟机容器之间的关系详解
问题 沙箱、虚拟化、容器三者分开一一介绍的话我知道他们各自都是什么东西,但是如果把三者放在一起,它们之间到底什么关系?又有什么联系呢?我不是很明白!!! 就比如说: 沙箱&#…...
如何配置一个sql server使得其它用户可以通过excel odbc获取数据
要让其他用户通过 Excel 使用 ODBC 连接到 SQL Server 获取数据,你需要完成以下配置步骤: ✅ 一、在 SQL Server 端配置(服务器设置) 1. 启用 TCP/IP 协议 打开 “SQL Server 配置管理器”。导航到:SQL Server 网络配…...

【免费数据】2005-2019年我国272个地级市的旅游竞争力多指标数据(33个指标)
旅游业是一个城市的重要产业构成。旅游竞争力是一个城市竞争力的重要构成部分。一个城市的旅游竞争力反映了其在旅游市场竞争中的比较优势。 今日我们分享的是2005-2019年我国272个地级市的旅游竞争力多指标数据!该数据集源自2025年4月发表于《地理学报》的论文成果…...