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 面试官:结婚了吗? 我:结婚了 面试官࿱…...

7.4.分块查找
一.分块查找的算法思想: 1.实例: 以上述图片的顺序表为例, 该顺序表的数据元素从整体来看是乱序的,但如果把这些数据元素分成一块一块的小区间, 第一个区间[0,1]索引上的数据元素都是小于等于10的, 第二…...
Java 8 Stream API 入门到实践详解
一、告别 for 循环! 传统痛点: Java 8 之前,集合操作离不开冗长的 for 循环和匿名类。例如,过滤列表中的偶数: List<Integer> list Arrays.asList(1, 2, 3, 4, 5); List<Integer> evens new ArrayList…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面
代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口(适配服务端返回 Token) export const login async (code, avatar) > {const res await http…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...

一些实用的chrome扩展0x01
简介 浏览器扩展程序有助于自动化任务、查找隐藏的漏洞、隐藏自身痕迹。以下列出了一些必备扩展程序,无论是测试应用程序、搜寻漏洞还是收集情报,它们都能提升工作流程。 FoxyProxy 代理管理工具,此扩展简化了使用代理(如 Burp…...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...