C++【模板初阶】
✨个人主页: Yohifo
🎉所属专栏: C++修行之路
🎊每篇一句: 图片来源
No one saves us but ourselves, no one can and no one may. We ourselves must walk the path.
- 除了我们自己,没有人能拯救我们,没有人可以,也没有人可以。我们自己必须走这条路。
文章目录
- 📘前言
- 📘正文
- 📖范型编程
- 📖函数模板
- 🖋️使用方法
- 🖋️实现原理
- 💡隐式实例化
- 💡显式实例化
- 🖋️匹配规则
- 🖋️注意事项
- 📖类模板
- 🖋️使用方法
- 🖋️注意事项
- 📘总结
📘前言
早在北宋年间,中国的毕昇就已经发明了泥活字
,标志着四大发明之一的活字印刷术
正式诞生,从此文化传播取得了革命性突破,各种文学作品得以走进千家万户。倘若这项技术还没有被发明,那么恐怕我们现在的书本都还得靠逐字手抄传播,效率是非常低的
我们的程序也是如此,很多需要频繁使用的函数每次都得手动写,这可难不倒程序员,于是在上世纪80年代末,范型编程
思想正式诞生,它就像是印刷文字的模具,将程序主体刻在其中,需要使用时让编译器
根据参数类型
生成即可,这就是我们今天的主角模板
📘正文
模板
的产生源自于范型编程
的思想,简单来说,就是将算法抽象化编写
📖范型编程
那么什么才是一个抽象化
的算法呢?
比如我们常用的两数相加函数,按照以前的写法,处理整型数据时,编写整型的方法;处理浮点型时,又得编写一个浮点型的加法,好在C++
支持函数重载
,使得我们可以存在同名函数,假若是C语言
实现时,我们甚至要写两个不同名的相加函数
//处理整型的加法函数
int Add(const int& a, const int& b)
{return a + b;
}//处理浮点型的加法函数
double Add(const double& a, const double& b)
{return a + b;
}
两数相加,直接返回两数之和就行了,我们实现方法时,没必要关注具体数据类型
将具体问题抽象化
,直接假设数据类型为 T
,利用模板
实现如下:
//利用模板实现函数
template <class T> //模板关键字
T Add(const T& a, const T& b)
{return a + b;
}
此时我们只编写了一个加法函数模板,而所有类型的参数都可以调用加法函数
具体问题抽象化就是范型编程
的核心思想
📖函数模板
首先来看模板
在函数实现上的运用
注意:
- 模板关键字为
template
- 形式为
template <class T>
或者template <typename T>
- 其中的
T
是模板中的参数名,我们可以自定义 - 模板中可以存在多个参数,通过
,
号分隔
🖋️使用方法
模板函数
即在函数实现之前,写好模板
,再根据模板
中定义的变量名实现函数
//实现所有类型数组的打印
//这种模板写法也是没有问题的
template <typename Type>
void CoutArray(const Type& arr)
{//范围 for ,C++11 中的语法糖for (auto e : arr){cout << e << " ";}cout << endl;
}
我们还可以实现多参数模板
//多参数模板
//这里实现的是val2强制类型转换为val1,并取得和
template <class T1, class T2>
T1 getTrunVal(const T1& val1, const T2& val2)
{const T1 tmp = (const T1)val2;return val1 + tmp;
}
总之,在函数模板
的存在下,我们不再需要再编写不同类型参数的相似函数了
🖋️实现原理
这个模板看着挺厉害,那么它的实现原理是什么呢?
其实很简单,只需要两样东西:编译器
和 函数重载
当我们编写好函数模板
后,编译器
会记住这个模板
的内容,当我们使用模板
时,编译器
又会根据参数类型,创建相应的、具体的函数供参数使用,而这就是函数重载
的道理
形象化理解:
- 假设我们的整个
程序
就是一个大城市 - 在这个城市中,我们就是
造物主
,编译器
则是负责协助我们处理事情的 - 假设在某一天,
参数A
提出它需要一栋房子(方法)
,造物主
很不屑的给造好了房子
- 一天后,
参数B
也说它也需要一栋房子(方法)
,造物主
很快就满足了它的需求 - 之后的每一天中,都会有
参数
说自己需要房子(方法)
,于是造物主
坐不住了,他觉得这些参数
很麻烦,明明大家都是同一个需求,还得自己不断重复实现 - 于是他想了一个办法:将建造房子的
图纸(模板)
交给编译器
,编译器
是完全服从于造物主
的,造物主
说:“小编啊,以后再有人找我建房子(方法)
,你就按照这个图纸(模板)
去建造,建好后将房子所有者变成它就行了”,这样一来,造物主
的工作量就减小了很多,重复相似的工作直接提供蓝图(模板)
,然后让编译器
根据参数类型
落实即可 - 于是,
函数模板
就这样诞生了
可以看出,不断建房子这件麻烦事仍然存在,毕竟不可能让所有参数都入住一栋房子,函数模板
的本质就是将实现不同参数的相似方法这件事交给编译器去完成,我们只需要提供蓝图(模板)
即可
比如文章开头中的 Add
函数,我们提供了模板
,当实际调用函数时,编译器会自动识别参数类型,然后生成对应的函数,供参数调用,也就是说,编译器根据不同参数,老老实实生成了 int
、double
、char
三个版本的 Add
函数,如果有需要,它还能继续生成
实际参数调用时,调用的是模板生成的对应函数,而非模板本身!
编译器在识别参数类型生成函数时,有两种途径:
- 自动识别 (
隐式
) - 我们手动指定(
显式
)
💡隐式实例化
隐式实例化
就是编译器自动识别参数后生成函数的过程
隐式实例化很方便,但可能存在问题
//Add 模板
template <class T>
T Add(const T& a, const T& b)
{return a + b;
}int main()
{Add(2, 1.5); //此时编译失败!return 0;
}
原因:
- 此时我们的模板是单参数模板
- 因为是编译器
隐式实例化
,当编译器识别到2
时,将生成int
型方法 - 此时
Add
函数内的两个形参类型都为int
,实际函数名修饰为_3Addii
- 而我们的参数2为
double
,是一个浮点型数据,实际函数调用时,找的是这个函数_3Addid
- 此时出现明显的链接错误,编译器索性直接在编译前就已经报错阻拦
解决方法:
- 将参数2强制类型转换为
int
,或者将参数1强制类型转换为double
都能解决问题 - 多参数模板也能解决问题,此时如果识别到两个不同的参数,编译器就会根据实际情况生成函数
- 还有一种解决方法就是
显式实例化
注意:
强制类型转换
后生成临时变量进行传参- 临时变量具有常性,所以Add函数中的引用形参需要被 const 修饰
- 或者不用引用,这样也不需要
const
,但是此时效率会变低
💡显式实例化
显式实例化
就是给编译器打招呼,让它在建房子时按照我们的意愿来
Add<int> (2, 3.14); //此时编译器会调用 _3Addii 函数,至于传参时的类型转换,由编译器完成
Add<char> (2, 5); //调用 _3Addcc 函数
这种行为是完全合法的,< >
符号也正式和我们见面了,在后面的 STL
学习中,< >
会经常使用到,比如生成一个类型为 int
的顺序表,直接 vector<int>
,生成 char
类型的顺序表 vector<char>
,一键生成,非常方便,当然还有很多容器都会用到显式实例化
🖋️匹配规则
具体函数调用时,隐式
生成的模板函数
并不会最先被调用
假设我们已经在程序中写好了参数需要的函数,而同时模板也能生成参数需要的函数,此时编译,编译器会先寻找是否存在目标函数,如果有,编译器便不再根据函数模板生成函数,避免造成代码冗余
我们可以通过调试来观察到这一现象
🖋️注意事项
注意:
- 函数调用时,并非直接调用
函数模板
,而是调用编译器
根据参数类型
和模板
生成的函数 - 使用模板是在麻烦
编译器
帮我们办事,实际事也是办成功的 - 当
隐式
实例化后的函数已存在时,不会去生成模板函数
,而是直接使用已存在的函数 显式
实例化后,编译器则会优先选择显式
生成的普通函数隐式
生成的模板函数不存在类型隐式类型转换
,显式
后生成的是普通函数,可以隐式类型转换
模板中的参数类型不能为 strcut
template<struct T> //这种定义是非法的
C++
库中存在一个 swap
函数,它能实现所有数据类型的交换,其实它就是通过函数模板
实现的
📖类模板
模板
除了可以用在函数
上面外,还可以用在类
上,此时称为 类模板
STL
库中的容器,都是 类模板
的形式,我们使用时,需要什么类型的 类
,直接显式实例化为对应 模板类
即可
//简单演示下 STL 中的容器,这些都是类模板的实际运用
vector<int> v1; //实例化为整型顺序表类
list<double> l1; //实例化为浮点型链表类
🖋️使用方法
类模板
和函数模板
有所不同,类模板
只能显式实例化
//简单写一个栈模板
template<class T>
class Stack
{
public://构造函数Stack(int capacity = 4);//析构函数~Stack();//……private:T* _pData;int _top;int _capacity;
};//注意类模板中方法的实现方式!
//定义构造函数
template<class T>
Stack<T>::Stack(int capacity)
{_pData = new T[capacity]; //内存管理,一次申请4块空间_capacity = capacity;_top = 0;
}//定义析构函数
template<class T>
Stack<T>::~Stack()
{delete[] _pData; //注意:匹配使用_capacity = _top = 0;
}//……
这就算 STL
库中 stack
的简陋版本,还有很多方法没实现,但大体逻辑都是如此
🖋️注意事项
类模板
使用时需要注意一些问题:
模板类
中的函数在定义时,如果没有在类域中,就需要通过类模板
+类域访问
的方式定义类模板
不支持声明与定义分开在两个文件中实现,因为会出现链接错误
📘总结
以上就是关于 C++ 模板初阶
的全部内容了,模板
是一个很实用的工具,它可以提高我们的编码效率,省去很多不必要的麻烦,善用模板
,快乐编程!
如果你觉得本文写的还不错的话,可以留下一个小小的赞👍,你的支持是我分享的最大动力!
如果本文有不足或错误的地方,随时欢迎指出,我会在第一时间改正
相关文章推荐 C/C++【内存管理】
===============
类和对象实操
类和对象实操之【日期类】
===============
类和对象系列
类和对象(下)
类和对象(中)
类和对象(上)
![]()
相关文章:

C++【模板初阶】
✨个人主页: Yohifo 🎉所属专栏: C修行之路 🎊每篇一句: 图片来源 No one saves us but ourselves, no one can and no one may. We ourselves must walk the path. 除了我们自己,没有人能拯救我们…...
华为OD机试 - 磁盘容量(Python)| 真题+思路+考点+代码+岗位
磁盘容量 题目 磁盘的容量单位常用的有M、G、T 他们之间的换算关系为1T =1024G,1G=1024M 现在给定n块磁盘的容量,请对他们按从小到大的顺序进行稳定排序 例如给定5块盘的容量 5 1T 20M 3G 10G6T 3M12G9M 排序后的结果为 20M 3G 3M12G9M 1T 10G6T 注意单位可以重复出现 上述…...

更专业、安全、可控!政企都选择WorkPlus私有化部署
现如今政企机构在信息化建设的过程中,内部的沟通协作都离不开即时通讯软件。但大多数企业使用的即时通讯软件都是Saas部署的,虽然使用Saas部署产品成本低,又方便快捷,但还是建议企业有条件最好使用私有化部署的即时通讯软件&#…...
[SDX12] X12 USB to LTE IPA概率不生效问题分析及优化策略
问题描述 在测试USB to LTE的流量过程中,发现IPA概率失效,正常可以跑到320Mbps,但是跑流1分钟左右会出现IPA失效及跑流掉坑的情况。 问题log dmesg log 3,1862,149793394,-;ipa ipa3_ioctl:3564 using obselete command: IPA_IOC_RM_ADD_DEPENDENCY 3,1863,149793549,-;ipa …...

mysql8.0(单表查询与多表拆线)
目录 单表查询 1、显示所有职工的基本信息。 2、查询所有职工所属部门的部门号,不显示重复的部门号。 3、求出所有职工的人数。 4、列出最高工资和最低工资。 5、列出职工的平均工资和总工资。 6、创建一个只有职工号、姓名和工作时间的新表&…...

用于汽车传感器的混合点云语义压缩:性能评估
Hybrid Point Cloud Semantic Compression for Automotive Sensors: A Performance Evaluation https://arxiv.org/pdf/2103.03819.pdf 在自动驾驶中,车辆与车辆之间的信息共享起着重要作用。在所有传感器中,激光雷达产生的3D点云的数据量通常较高。因…...
最流行十大在线客服系统排行榜-市场常见客服系统软件排行-2023最新
2023年榜单规则依据 在线客服系统十大品牌榜数据由CNPP品牌榜中榜大数据「研究院」和CN10排排榜技术「研究院」通过资料收集整理,并基于大数据统计及人为根据市场和参数条件变化的分析研究专业测评而得出,是大数据、云计算、数据统计真实客观呈现的结果&…...
算法笔记(六)—— 二叉树相关概念及经典算法题
二叉树的相关概念(判断方式) 1. 搜索二叉树:对每棵子树,左树比头小,右树比头大。 中序遍历,判断是否升序 2. 完全二叉树:最后一层满或从左到右遍满。 宽度遍历,如果有节点有右孩子…...
redux全网最详细教程
一.路由懒加载 关键点: lazy懒加载 Suspense组件(添加加载提示) utils文件夹 –LazyLoad.js //lazy懒加载 Suspense 组件(添加加载提示) import {lazy,Suspense} from react export default function LazyLoad(url)…...
华为OD机试 - 匿名信(Python)| 真题+思路+考点+代码+岗位
匿名信 题目 电视剧《分界线》里面有一个片段,男主为了向警察透露案件细节,且不暴露自己,于是将报刊上的字减下来,剪拼成匿名信。 现在又一名举报人,希望借鉴这种手段,使用英文报刊完成举报操作。 但为了增加文章的混淆度,只需满足每个单词中字母数量一致即可,不关注…...

【Python】编写代码实现指定下标值顺序进行正序和倒序排序算法编程
🎉🎉 在本次python文章中,主要通过定义一个排序方法,实现一组数列能够按照另一组数列指定的位置进行重新排序输出,默认正序排序,可通过True表示逆序输出 目录1、知识点2、数列和元组1)错误遍历方…...

Sitara™处理器的产品开发路线图
Sitara™处理器的产品开发路线图概述Evaluation Phase(评估阶段)Board Development Phase(硬件发展阶段,硬件设计人员应重点关注这个阶段)Software Development Phase(软件发展阶段)Product Phase/SW Lifecycle概述 一般情况下,会存在四个主要的发展阶段…...
岗位来啦-华为研发OD招聘
研发OD招聘 ★★关于我们★★ 万物互联时代已到来,无线通信技术正在重塑世界。作为行业领导者,华为无线致力于通过移动创新消除数字鸿沟,构建万物互联的智能世界。基于5G的技术,家庭无线宽带接入、车联网、云AR/VR、eMBB高清视频…...

【LeetCode】剑指 Offer 06. 从尾到头打印链表 p58 -- Java Version
题目链接: https://leetcode.cn/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/ 1. 题目介绍(06. 从尾到头打印链表) 输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)。 【测试用例…...

童年回忆--扫雷(包括标记功能和递归展开)--万字讲解让你学会扫雷制作
魔王的介绍:😶🌫️一名双非本科大一小白。魔王的目标:🤯努力赶上周围卷王的脚步。魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥 ❤️…...
【重器】GPS北斗卫星时钟基准与卫星授时服务技术原理
【重器】GPS北斗卫星时钟基准与卫星授时服务技术原理 【重器】GPS北斗卫星时钟基准与卫星授时服务技术原理 1.前言 由计算机网络系统组成的分布式系统,若想协调一致进行:IT行业的“整点开拍”、“秒杀”、“Leader选举”,通信行业的“同步组网…...

软件测试未来发展趋势怎么样
未来,互联网技术是很多企业能够活下去的关键点。互联网技术成为新的基建,互联网“基建”化就决定了软件测试行业的缺口会一直扩大。 并且,软件测试岗位,已不仅局限于互联网企业,现已逐步深入到实体产业,金…...

aws Distro for OpenTelemetry 可观测性workshop记录
参考资料 https://aws-otel.github.io/docs/introductionhttps://aws-otel.github.io/docs/introduction aws distro for opentelemetry 官方提供了不同语言不同使用场景下完善的使用实例和相关配置。 AWS Distro for OpenTelemetrics 由以下部分组成,用于向后端…...
Leetcode力扣秋招刷题路-0068
从0开始的秋招刷题路,记录下所刷每道题的题解,帮助自己回顾总结 68. 文本左右对齐 给定一个单词数组 words 和一个长度 maxWidth ,重新排版单词,使其成为每行恰好有 maxWidth 个字符,且左右两端对齐的文本。 你应该…...

Nginx介绍及安装(windows版,Linux版)
目录 一、Nginx介绍 1、Nginx优势 2、Nginx作用 3、部署静态资源 4、代理 5、负载均衡 二、Nginx安装步骤(windows版) 三、Nginx安装步骤(Linux版) 1、官网下载安装包,下载完之后上传到Linux系统上 2、在Lin…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘
美国西海岸的夏天,再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至,这不仅是开发者的盛宴,更是全球数亿苹果用户翘首以盼的科技春晚。今年,苹果依旧为我们带来了全家桶式的系统更新,包括 iOS 26、iPadOS 26…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
React---day11
14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store: 我们在使用异步的时候理应是要使用中间件的,但是configureStore 已经自动集成了 redux-thunk,注意action里面要返回函数 import { configureS…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测
uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...
解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist
现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...
华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)
题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里
写一个shell脚本,把局域网内,把能ping通的IP和不能ping通的IP分类,并保存到两个文本文件里 脚本1 #!/bin/bash #定义变量 ip10.1.1 #循环去ping主机的IP for ((i1;i<10;i)) doping -c1 $ip.$i &>/dev/null[ $? -eq 0 ] &&am…...