C++模板初阶
C++模板初阶
- 泛型编程
- 函数模板
- 概念
- 函数模板格式
- 函数模板原理
- 函数模板的实例化
- 模板参数的匹配原则
- 类模板
- 类模板的定义格式
- 类模板的实例化
泛型编程
我们前面学习了C++的函数重载功能,那么我们如何实现一个通用的交换函数呢,比如:我传入int就是交换int,传入double就进行double类型的交换……
void Swap( int& a, int& b)
{int temp = a;a = b;b = temp;
}
void Swap(double& a, double& b)
{double temp = a;a = b;b = temp;
}
void Swap(char& a, char& b)
{char temp = a;a = b;b = temp;
}
void Swap(int*& a, int*& b)
{int* temp = a;a = b;b = temp;
}
我们可以发现尽管有了函数重载的技术,但是我们还是避免不了所有问题;我们很难写出一个通用的Swap函数,如果我们每增加一个新类型,我们就得重新写一个Swap函数,很麻烦!那么有没有什么办法让我只写一份通用的代码,所有类型都可以用呢?当然有!对于C语言的这种不足,C++在此基础上提出了泛型编程的概念:就是对于一些所有类型都可通用的代码,比如Swap这种我们在写具体实现的时候可以假装我们的数据类型是通用的,然后在对其进行处理,当我们在调用该函数的时候,编译器会自动推演出数据的具体类型,这就好比我们在写方程一样,我们先假设未知数,将未知数先当成已知,最后在解出未知数!这里自动推演数据类型的过程就相当于在解方程!
这个编写通用代码的过程就是在造模子通过给这个模子传递不同的参数类型,来确定具体的数据类型,从而获得具体类型对应的代码,生成具体类型代码的过程是由编译器来帮助我们完成的,我们无需在自己手动写了;
在C++中模板是泛型编程的基础!
模板又分为:函数模板、类模板;

函数模板
概念
函数模板代表了一个函数家族,该函数模板与类型无关,在使用参数时,由编译器根据所传参数类型自动推演函数参数的具体类型,由此产生特定类型的函数版本,这个过程,被称为实例化;
函数模板格式
template<class 类型参数名1,class 类型参数名2,…… >
返回类型 函数名(参数列表)
或者
template<typename 类型参数名1,typename 类型参数名2……>;
返回类型 函数名(参数列表)
注意:typename是用来定义模板参数的关键字,class也可以,但是struct不可以;
实例:写一个通用的交换函数:
template <typename T>
void Swap(T& a, T& b)
{T tmp = a;a = b;b = tmp;
}

函数模板原理
么如何解决上面的问题呢?大家都知道,瓦特改良蒸汽机,人类开始了工业革命,解放了生产力。机器生产淘汰掉了很多手工产品。本质是什么,重复的工作交给了机器去完成。有人给出了论调:懒人创造世界。

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器;
函数模板的实例化
用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化;
1、隐式实例化
上述Add的调用,就是隐式实例化,编译器会根据我们传递给Add的参数自动推演出类型参数的具体类型,以此来生成具体类型的交换函数来给我们用;
当然我们不能乱传递参数类型,比如:Add(a,x);
编译器在调用该Add函数的时候,根据左参数类型先推演出类型参数T为int类型,然后又根据有参数类型推演出类型参数T为double类型,那么参数类型到底具体为那个类型?这就会让编译器陷入歧义,编译器也就会报错,Add函数也就无法正确实例化!类型参数,会根据以第一次推演出的结果作为默认类型,与auto在一排的用法差不多,但是模板无法完成参数的隐式转换!
那如果我们就是要调用Add(a,x);函数应该怎么办?
有两种解决办法:
1、强转a,或强转x,就是将a,x的类型转换成一致的;
2、显示实例化;
2、显示实例化:
就是明确指定类型参数的具体类型,不需要编译器再根据参数类型自动推演了;明确指定参数的具体类型过后,编译器就会自动生成具体函数,来供调用处使用!
比如上述的Add(a,x)
我们像这样做:Add<int>(a,x);显示的指定类型参数为int,编译器就会自动生成参数类型为int的Add函数:
如果类型不匹配编译器会自动尝试隐式转换!无法完成完成隐式类型转换的编译器直接报错;
这里的隐式类型转换与上面隐式调用的类型转换不一样,这里使明确规定了类型参数的具体类型,也就是先生成了具体函数,才有的隐式类型转换;上面是根据参数类型推演类型参数的具体类型,然后再生成匹配的函数,参数不匹配,无法生成具体函数,怎么能进行隐式转换呢?
模板参数的匹配原则
1、非模板函数与函数模板同名,同时函数模板还可以实例化成非模板函数,编译器会优先调用非模板函数;
为什么会出现这种情况呢?
编译器是很聪明的,如果我们去调用函数模板时,编译器会首先根据参数类型推演出类型参数的具体类型,然后实例化出具体的Add函数来调用,你看啊,现在我明明有现成的Add函数可以用,那么我们为什么还要去实例化,再调用呢?这不是脱了裤子放屁,多此一举嘛!
那如果我们非要调用模板实例化出来的Add函数,该怎么办呢?
当然是显示调用:
2、对于非模板函数与同名函数模板,其他条件都相同,但是非模板函数的参数类型与调用处的类型不一样,编译器会根据函数模板实例化出最匹配的函数来调用:
3、对于隐式实例化函数模板,不会发生隐式类型转换;对于显示实例化函数模板,可以发生隐式类型转换;
类模板
类模板的定义格式
template<class T1,class T2,class T3,……>
class 类模板名
{
//类成员定义;
};
比如现在我们写一个栈类模板:
template <class T>
class Stack
{Stack(){int capacity = 4;_a = new T[capacity];_top = 0;_capacity = capacity;}~Stack(){delete[] _a;_top = _capacity = 0;}
private:T* _a;int _top;int _capacity;
};
类模板中的成员函数全是模板函数
然后注意此时的Stack不是具体的类,而是编译器根据被实例化的类型生成具体类的模具;
同时类模板的成员函数也可以实现在类内声明,类外定义;
只不过与我们平时写的具体的类的定义方式不太一样:
比如现在我在类内声明构造函数,类外定义构造函数:
这样我们既能定义基本数据类型为double的栈,也可以定义基本数据类型为int的栈了:
这时候或许会有读者说,我用typedef也能做到类型替换啊,可是typedef不能做到Stack<int>与Stack<double>两种栈同时存在啊,如果想要这两个栈同时存在,我们就只能再重新定义一个栈,这样很是麻烦!
同时不建议类模板的声明与函数定义分离!
类模板的实例化
类模板的实例化与函数模板的实例化不同,类模板实例化只能通过显示实例化,不能隐式实例化:

相关文章:
C++模板初阶
C模板初阶泛型编程函数模板概念函数模板格式函数模板原理函数模板的实例化模板参数的匹配原则类模板类模板的定义格式类模板的实例化泛型编程 我们前面学习了C的函数重载功能,那么我们如何实现一个通用的交换函数呢,比如:我传入int就是交换intÿ…...
文献阅读:Scaling Instruction-Finetuned Language Models
文献阅读:Scaling Instruction-Finetuned Language Models 1. 文章简介2. 实验 1. 数据集 & 模型 1. 数据集考察2. 使用模型 2. scale up对模型效果的影响3. CoT对模型效果的影响4. 不同模型下Flan的影响5. 开放接口人工标注指标 3. 结论 文献链接:…...
gpt草稿
ChatgptWhatChatGPT(全名:Chat Generative Pre-trained Transformer [2])是由OpenAI开发的一个人工智能聊天机器人程序,于2022年11月推出。该程序使用基于GPT-3.5架构的大型语言模型并通过强化学习进行训练。ChatGPT里面有两个词&…...
mysal第三次作业
1、显示所有职工的基本信息。 2、查询所有职工所属部门的部门号,不显示重复的部门号。 3、求出所有职工的人数。 4、列出最高工和最低工资。 5、列出职工的平均工资和总工资。 6、创建一个只有职工号、姓名和参加工作的新表,名为工作日期表…...
分页和mmap
文章目录一、内存分页1、基本概念2、分页机制下,虚拟地址和物理地址是如何映射的?3、快表(TLB)二、mmap基本原理和分类一、内存分页 1、基本概念 CPU并不是直接访问物理内存地址,而是通过虚拟地址空间来间接的访问物理内存地址。 页&#x…...
C++之异常处理
异常异常是面向对象语言处理错误的一种方式。当一个函数出现自己无法处理的错误时,可以抛出异常,然后输的直接或者间接调用者处理这个错误。语法捕获全部的异常try {//可能抛出异常的代码//throw异常对象 } catch(...) {//不管什么异常,都在这…...
牛客寒假集训营6 E 阿宁的生成树
E-阿宁的生成树_2023牛客寒假算法基础集训营6 (nowcoder.com)开始慢慢补牛牛的题题意:最小生成树质数距离思路:最小生成树一共就两种算法,我们考虑Prim的过程初始连通块是1,然后考虑拿1和其他的结点连边当j-i<k时边权是gcd&…...
嵌入式C基础知识(10)
C语言如何实现一个频繁使用短小函数,C如何实现?C语言可以使用宏定义实现一个短小函数,如下面例子所示。但是宏定义语句不会进行检查,并且对书写格式有过分的讲究。比如MAX和括号之间不能有空格,每个参数都要放在括号里…...
TC3xx FlexRay™ 协议控制器 (E-Ray)-01
1 FlexRay™ 协议控制器 (E-Ray) E-Ray IP 模块根据为汽车应用开发的 FlexRay™ 协议规范 v2.1 执行通信【performs communication according to the FlexRay™ 1) protocol specification v2.1】。使用最大指定时钟,比特率可以编程为高达 10 Mbit/s 的值。连接到物…...
优劣解距离法TOPSIS——清风老师
TOPSIS法是一种常用的综合评价方法,能充分利用原始数据的信息,其结果能精确地反映各评价方案之间的差距。 基本过程为先将原始数据矩阵统一指标类型(一般正向化处理)得到正向化的矩阵,再对正向化的矩阵进行标准化处理…...
【Unity3D】Shader常量、变量、结构体、函数
1 源码路径 Unity Shader 常量、变量、结构体、函数一般可以在 Unity Editor 安装目录下面的【Editor\Data\CGIncludes\UnityShader】目录下查看源码,主要源码文件如下: UnityCG.cgincUnityShaderUtilities.cgincUnityShaderVariables.cginc 2 Shader 常…...
LeetCode 刷题系列 -- 496. 下一个更大元素 I
nums1 中数字 x 的 下一个更大元素 是指 x 在 nums2 中对应位置 右侧 的 第一个 比 x 大的元素。给你两个 没有重复元素 的数组 nums1 和 nums2 ,下标从 0 开始计数,其中nums1 是 nums2 的子集。对于每个 0 < i < nums1.length ,找出满…...
Docker 搭建本地私有仓库
一、搭建本地私有仓库有时候使用Docker Hub这样的公共仓库可能不方便,这种情况下用户可以使用registry创建一个本地仓库供私人使用,这点跟Maven的管理类似。使用私有仓库有许多优点:1)节省网络带宽,针对于每个镜像不用…...
XML中的CDATA且mybatis中特殊字符转义
如果想看如果CDATA在mybatis的xml文件中使用的可以直接跳转。 CDATA1 XML中的CDATA1.1 为什么叫CDATA1.2 CDATA在XML中的语法1.3 CDATA在XML中的例子1.4 CDATA规则2 Mybatis中的CDATA2.1 Mybatis中使用XML转义序列转义2.2 Mybatis中使用CDATA转义2.3 mybatis中使用CDATA需注意的…...
位运算 | 1356. 根据数字二进制下 1 的数目排序
LeetCode 1356. 根据数字二进制下 1 的数目排序 给你一个整数数组 arr 。请你将数组中的元素按照其二进制表示中数字 1 的数目升序排序。如果存在多个数字二进制中 1 的数目相同,则必须将它们按照数值大小升序排列。 文章讲解https://www.programmercarl.com/1356.%…...
React Hooks之useState详解
1. 什么是Hooks? React官方简介:Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。 本文中讲解的useState就是React中的其中一个Hook。 2. useState useState 通过在函数组件里调用它来满足给组件添…...
选购交换机的参数依据和主要的参数指标详解
如何选购交换机?用什么交换机?在选购交换机时交换机的优劣无疑十分的重要,而交换机的优劣要从总体构架、性能和功能三方面入手。交换机选购时。性能方面除了要满足RFC2544建议的基本标准,即吞吐量、时延、丢包率外,随着…...
Connext DDS属性配置参考大全(1)
介绍属性QoS策略存储名称/值(字符串)对,可用于配置Connext DDS的某些参数,这些参数未通过正式的QoS策略公开。 属性QoS策略存储实体的名称/值对。名称和值都是字符串。在核心库用户手册的“Property QosPolicy(DDS Extension)”部分中找到有关RTI Connext DDS属性QoS的更…...
Docker安全
容器的安全性问题的根源在于容器和宿主机共享内核。如果容器里的应用导致Linux内核崩溃,那么整个系统可能都会崩溃。 与虚拟机是不同的,虚拟机并没有与主机共享内核,虚拟机崩溃一般不会导致宿主机崩溃 一、Docker 容器与虚拟机的区别 1、隔…...
刷题记录:牛客NC20279[SCOI2010]序列操作
传送门:牛客 题目描述: lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作: 0 a b 把[a, b]区间内的所有数全变成0 1 a b 把[a, b]区间内的所有数全…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
PAN/FPN
import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...
Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解
文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一:HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二:Floyd 快慢指针法(…...
Appium下载安装配置保姆教程(图文详解)
目录 一、Appium软件介绍 1.特点 2.工作原理 3.应用场景 二、环境准备 安装 Node.js 安装 Appium 安装 JDK 安装 Android SDK 安装Python及依赖包 三、安装教程 1.Node.js安装 1.1.下载Node 1.2.安装程序 1.3.配置npm仓储和缓存 1.4. 配置环境 1.5.测试Node.j…...
SQL注入篇-sqlmap的配置和使用
在之前的皮卡丘靶场第五期SQL注入的内容中我们谈到了sqlmap,但是由于很多朋友看不了解命令行格式,所以是纯手动获取数据库信息的 接下来我们就用sqlmap来进行皮卡丘靶场的sql注入学习,链接:https://wwhc.lanzoue.com/ifJY32ybh6vc…...
中科院1区顶刊|IF14+:多组学MR联合单细胞时空分析,锁定心血管代谢疾病的免疫治疗新靶点
中科院1区顶刊|IF14:多组学MR联合单细胞时空分析,锁定心血管代谢疾病的免疫治疗新靶点 当下,免疫与代谢性疾病的关联研究已成为生命科学领域的前沿热点。随着研究的深入,我们愈发清晰地认识到免疫系统与代谢系统之间存在着极为复…...








