当前位置: 首页 > news >正文

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 函数,我们提供了模板,当实际调用函数时,编译器会自动识别参数类型,然后生成对应的函数,供参数调用,也就是说,编译器根据不同参数,老老实实生成了 intdoublechar 三个版本的 Add 函数,如果有需要,它还能继续生成

实际参数调用时,调用的是模板生成的对应函数,而非模板本身!

编译器在识别参数类型生成函数时,有两种途径:

  1. 自动识别 (隐式)
  2. 我们手动指定(显式)

💡隐式实例化

隐式实例化就是编译器自动识别参数后生成函数的过程

隐式实例化很方便,但可能存在问题

//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 函数,它能实现所有数据类型的交换,其实它就是通过函数模板实现的
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++【模板初阶】

✨个人主页&#xff1a; Yohifo &#x1f389;所属专栏&#xff1a; C修行之路 &#x1f38a;每篇一句&#xff1a; 图片来源 No one saves us but ourselves, no one can and no one may. We ourselves must walk the path. 除了我们自己&#xff0c;没有人能拯救我们&#xf…...

华为OD机试 - 磁盘容量(Python)| 真题+思路+考点+代码+岗位

磁盘容量 题目 磁盘的容量单位常用的有M、G、T 他们之间的换算关系为1T =1024G,1G=1024M 现在给定n块磁盘的容量,请对他们按从小到大的顺序进行稳定排序 例如给定5块盘的容量 5 1T 20M 3G 10G6T 3M12G9M 排序后的结果为 20M 3G 3M12G9M 1T 10G6T 注意单位可以重复出现 上述…...

更专业、安全、可控!政企都选择WorkPlus私有化部署

现如今政企机构在信息化建设的过程中&#xff0c;内部的沟通协作都离不开即时通讯软件。但大多数企业使用的即时通讯软件都是Saas部署的&#xff0c;虽然使用Saas部署产品成本低&#xff0c;又方便快捷&#xff0c;但还是建议企业有条件最好使用私有化部署的即时通讯软件&#…...

[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、查询所有职工所属部门的部门号&#xff0c;不显示重复的部门号。 3、求出所有职工的人数。 4、列出最高工资和最低工资。 5、列出职工的平均工资和总工资。 6、创建一个只有职工号、姓名和工作时间的新表&…...

用于汽车传感器的混合点云语义压缩:性能评估

Hybrid Point Cloud Semantic Compression for Automotive Sensors: A Performance Evaluation https://arxiv.org/pdf/2103.03819.pdf 在自动驾驶中&#xff0c;车辆与车辆之间的信息共享起着重要作用。在所有传感器中&#xff0c;激光雷达产生的3D点云的数据量通常较高。因…...

最流行十大在线客服系统排行榜-市场常见客服系统软件排行-2023最新

2023年榜单规则依据 在线客服系统十大品牌榜数据由CNPP品牌榜中榜大数据「研究院」和CN10排排榜技术「研究院」通过资料收集整理&#xff0c;并基于大数据统计及人为根据市场和参数条件变化的分析研究专业测评而得出&#xff0c;是大数据、云计算、数据统计真实客观呈现的结果&…...

算法笔记(六)—— 二叉树相关概念及经典算法题

二叉树的相关概念&#xff08;判断方式&#xff09; 1. 搜索二叉树&#xff1a;对每棵子树&#xff0c;左树比头小&#xff0c;右树比头大。 中序遍历&#xff0c;判断是否升序 2. 完全二叉树&#xff1a;最后一层满或从左到右遍满。 宽度遍历&#xff0c;如果有节点有右孩子…...

redux全网最详细教程

一.路由懒加载 关键点&#xff1a; lazy懒加载 Suspense组件&#xff08;添加加载提示&#xff09; utils文件夹 –LazyLoad.js //lazy懒加载 Suspense 组件&#xff08;添加加载提示&#xff09; import {lazy,Suspense} from react export default function LazyLoad(url)…...

华为OD机试 - 匿名信(Python)| 真题+思路+考点+代码+岗位

匿名信 题目 电视剧《分界线》里面有一个片段,男主为了向警察透露案件细节,且不暴露自己,于是将报刊上的字减下来,剪拼成匿名信。 现在又一名举报人,希望借鉴这种手段,使用英文报刊完成举报操作。 但为了增加文章的混淆度,只需满足每个单词中字母数量一致即可,不关注…...

【Python】编写代码实现指定下标值顺序进行正序和倒序排序算法编程

&#x1f389;&#x1f389; 在本次python文章中&#xff0c;主要通过定义一个排序方法&#xff0c;实现一组数列能够按照另一组数列指定的位置进行重新排序输出&#xff0c;默认正序排序&#xff0c;可通过True表示逆序输出 目录1、知识点2、数列和元组1&#xff09;错误遍历方…...

Sitara™处理器的产品开发路线图

Sitara™处理器的产品开发路线图概述Evaluation Phase(评估阶段)Board Development Phase(硬件发展阶段&#xff0c;硬件设计人员应重点关注这个阶段)Software Development Phase(软件发展阶段)Product Phase/SW Lifecycle概述 一般情况下&#xff0c;会存在四个主要的发展阶段…...

岗位来啦-华为研发OD招聘

研发OD招聘 ★★关于我们★★ 万物互联时代已到来&#xff0c;无线通信技术正在重塑世界。作为行业领导者&#xff0c;华为无线致力于通过移动创新消除数字鸿沟&#xff0c;构建万物互联的智能世界。基于5G的技术&#xff0c;家庭无线宽带接入、车联网、云AR/VR、eMBB高清视频…...

【LeetCode】剑指 Offer 06. 从尾到头打印链表 p58 -- Java Version

题目链接&#xff1a; https://leetcode.cn/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof/ 1. 题目介绍&#xff08;06. 从尾到头打印链表&#xff09; 输入一个链表的头节点&#xff0c;从尾到头反过来返回每个节点的值&#xff08;用数组返回&#xff09;。 【测试用例…...

童年回忆--扫雷(包括标记功能和递归展开)--万字讲解让你学会扫雷制作

魔王的介绍&#xff1a;&#x1f636;‍&#x1f32b;️一名双非本科大一小白。魔王的目标&#xff1a;&#x1f92f;努力赶上周围卷王的脚步。魔王的主页&#xff1a;&#x1f525;&#x1f525;&#x1f525;大魔王.&#x1f525;&#x1f525;&#x1f525; ❤️‍&#x1…...

【重器】GPS北斗卫星时钟基准与卫星授时服务技术原理

【重器】GPS北斗卫星时钟基准与卫星授时服务技术原理 【重器】GPS北斗卫星时钟基准与卫星授时服务技术原理 1.前言 由计算机网络系统组成的分布式系统&#xff0c;若想协调一致进行&#xff1a;IT行业的“整点开拍”、“秒杀”、“Leader选举”&#xff0c;通信行业的“同步组网…...

软件测试未来发展趋势怎么样

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

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 由以下部分组成&#xff0c;用于向后端…...

Leetcode力扣秋招刷题路-0068

从0开始的秋招刷题路&#xff0c;记录下所刷每道题的题解&#xff0c;帮助自己回顾总结 68. 文本左右对齐 给定一个单词数组 words 和一个长度 maxWidth &#xff0c;重新排版单词&#xff0c;使其成为每行恰好有 maxWidth 个字符&#xff0c;且左右两端对齐的文本。 你应该…...

Nginx介绍及安装(windows版,Linux版)

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

Camera | 4.瑞芯微平台MIPI摄像头应用程序编写

前面3篇我们讲解了camera的基础概念&#xff0c;MIPI协议&#xff0c;CSI2&#xff0c;常用命令等&#xff0c;本文带领大家入门&#xff0c;如何用c语言编写应用程序来操作摄像头。 Linux下摄像头驱动都是基于v4l2架构&#xff0c;要基于该架构编写摄像头的应用程序&#xff…...

【1250. 检查「好数组」】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个正整数数组 nums&#xff0c;你需要从中任选一些子集&#xff0c;然后将子集中每一个数乘以一个 任意整数&#xff0c;并求出他们的和。 假如该和结果为 1&#xff0c;那么原数组就是一个「…...

Spring 如何解决循环依赖?

什么是循环依赖 &#xff1f; 一个或多个对象之间存在直接或间接的依赖关系&#xff0c;这种依赖关系构成一个环形调用&#xff0c;有下面 3 种方式。 我们看一个简单的 Demo&#xff0c;对标“情况 2”。 Service public class Louzai1 {Autowiredprivate Louzai2 louzai2;…...

CocoaPods使用指南

前言 对于大多数软件开发团队来说&#xff0c;依赖管理工具必不可少&#xff0c;它能针对开源和私有依赖进行安装与管理&#xff0c;从而提升开发效率&#xff0c;降低维护成本。针对不同的语言与平台&#xff0c;其依赖管理工具也各有不同&#xff0c;例如 npm 管理 Javascri…...

Kafka 消息队列

目录主流的消息队列消息队列的应用场景缓存/肖锋解耦异步处理KafkaKafka的定义Kafka的底层基础架构Kafka分区如何保证Leader选举Kafka分区如何保证Leader和Follower数据的一致性Kafka 中消费者的消费方式Kafka 高效读写数据的原因&#xff08;高性能吞吐的原因&#xff09;&…...

华为OD机试 - 挑选字符串(Python)| 真题+思路+考点+代码+岗位

挑选字符串 题目 给定a-z,26 个英文字母小写字符串组成的字符串A和B, 其中A可能存在重复字母,B不会存在重复字母, 现从字符串A中按规则挑选一些字母可以组成字符串B 挑选规则如下: 同一个位置的字母只能挑选一次, 被挑选字母的相对先后顺序不能被改变, 求最多可以同时…...

对比Hashtable、HashMap、TreeMap有什么不同?

第9讲 | 对比Hashtable、HashMap、TreeMap有什么不同&#xff1f; Map 是广义 Java 集合框架中的另外一部分&#xff0c;HashMap 作为框架中使用频率最高的类型之一&#xff0c;它本身以及相关类型自然也是面试考察的热点。 今天我要问你的问题是&#xff0c;对比 Hashtable、…...

测试新版Android Studio的手机镜像效果

学更好的别人&#xff0c; 做更好的自己。 ——《微卡智享》 本文长度为669字&#xff0c;预计阅读2分钟 前言 春节刚上班&#xff0c;就开始了疯狂出差的节奏&#xff0c;期间发现Android Studio发布新的版本2022.1.1(Electric Eel)&#xff0c;里面两个更新的内容蓝牙模拟器和…...

女生可以参加IT培训吗?

2023年了&#xff0c;就不要把性别当作选择专业的前提条件了。虽然这句话说过很多次了&#xff0c;作为IT行业来说&#xff0c;是非常欢迎女生的加入&#xff1b;尤其是整天都是面对一大堆男攻城狮&#xff0c;工作氛围一点都不活跃&#xff0c;反而显得压抑和杂乱&#xff0c;…...

刷题25-重排链表

重排链表 解题思路&#xff1a;通过观察链表可以发现&#xff0c;把链表一分为二&#xff0c;后半段链表反转&#xff0c;然后两个链表穿插连接&#xff0c;当链表的节点总数是奇数时&#xff0c;要保证链表的前半段比后半段多一个节点。 关于把链表一分为二&#xff0c;可以…...

科讯cms怎么做网站地图/深圳搜索优化排名

如何快速清理 docker 资源 原文:如何快速清理 docker 资源如果经常使用 docker&#xff0c;你会发现 docker 占用的资源膨胀很快&#xff0c;其中最明显也最容易被察觉的应该是对磁盘空间的占用。本文将介绍如何快速的清理 docker 占用的系统资源&#xff0c;具体点说就是删除那…...

东营seo网站建设费用/营销策划与运营公司

当用户退出的时候&#xff0c;清除redis中token&#xff0c;其实很简单 我直接在oauth服务中新建一个接口 RestController RequestMapping("/authentication") public class UserController {AutowiredQualifier("consumerTokenServices")private Consume…...

网站的新闻模块怎么做/网站内容seo

I just dont wanna give them any more ammunition than they already have.---《老友记》 第一季 第一集 我只是不想&#xff0c;让他们有藉题发挥的机会。 名词 n. [U] 1. 弹药,军火The ammunition depot is heavily guarded. 弹药库戒备森严。 2. 【喻】"炮弹"(指…...

行业网站建设哪家好/百度竞价排名费用

这两年&#xff0c;线上办公逐渐常态化&#xff0c;相信大家对ftp这个概念也比较熟悉了。ftp&#xff0c;即文件传输协议&#xff0c;线上办公就是用ftp软件进行文件传输的。那ftp传输文件大小有限制吗,ftp文件传输工具有哪些我们一起来看看。 一、ftp传输文件大小有限制吗 f…...

古尔邦节网站建设/怎么发帖子做推广

题意&#xff1a;给一个无向无环图(n<1000)&#xff0c;在尽量少的节点上放灯&#xff0c;使得所有边都被照亮&#xff0c;灯可以照亮相邻的边&#xff0c;在灯数最小的前提下&#xff0c;使得被两盏灯照亮的边最多&#xff0c;输出灯数以及被两盏灯照亮的边数&#xff0c;及…...

幼儿园网站建设费用/百度平台订单查询

描述一个业务问题的现状是什么&#xff0c;是最基础的数据分析需求。常见的问题类型有&#xff1a;产品经理&#xff1a;某个功能的数据表现如何&#xff1f;活动运营&#xff1a;某个活动的数据情况怎么样&#xff1f;渠道运营&#xff1a;新渠道的引流人数是多少。新人数据分…...