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

【C++】模板的一点简单介绍

模板

    • 前言
    • 泛型编程
    • 函数模板
      • 概念
      • 格式
      • 函数模板的原理
      • 函数模板的实例化
    • 类模板
      • 类模板的定义格式
      • 类模板的实例化

在这里插入图片描述

前言

这篇博客讲的是模板的一些基本知识,并没有那么深入,但是如果你是为了过期末考试而搜的这篇博客,我觉得下面讲的是够了的。

之后会再出一篇深入讲解模板的博客。

泛型编程

先说一个例子:

如何实现一个通用的交换函数呢?

学了C++之后,我们有了函数重载这个东西。这是C不具有的语法。
我们可以通过函数重载来实现相同函数名交换不同类型的变量。像下面这样:

void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}
void Swap(double& left, double& right)
{double temp = left;left = right;right = temp;
}
void Swap(char& left, char& right)
{char temp = left;left = right;right = temp;
}

当然用C也可以,但是C实现的话,只能搞成不同函数名来实现不同变量的交换,而且还没有引用的语法。

但是不论是上面的函数重载还是用C来实现,都好麻烦,当我们每次想要交换新类型的交换的时候都要再重写一个函数。

也就是下面的缺点:

  1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数
  2. 代码的可维护性比较低,一个出错可能所有的重载均出错

活字印刷,相信大家都听过。

在这里插入图片描述

通过改变模具中的字来印刷出不同的文章。

那能否告诉编译器一个模具,让编译器根据不同的类型利用该模具来生成代码呢?

如果在C++中,也能够存在这样一个模具,通过给这个模具中填充不同文字块(类型),来获得不同文字的文章(即生成具体类型的代码)。

这就是本篇博客要讲的模板。

目录中的泛型编程是指编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。

模板分为两类,函数模板和类模板。
在这里插入图片描述

函数模板

概念

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

格式

//写函数前要加这个
template<typename T1, typename T2,......,typename Tn>
//typename后面的T1,这种就相当于我们定义变量时候的变量名,是
//随便取的,只不过这里是类型名。常用的还有K,V,跟T合起来就是KTV。//然后再写函数
返回值类型 函数名(参数列表){}

来个交换的例子:
在这里插入图片描述
下面都是OK的。
在这里插入图片描述

typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class)。

在这里插入图片描述
目前阶段,记住写成typename和class都是可以的。

再来个交换int和交换double的例子:
在这里插入图片描述
但是记住,上面的代码中,交换int和交换double走的不是一个函数。

函数模板的原理

大家都知道,瓦特改良蒸汽机,人类开始了工业革命,解放了生产力。机器生
产淘汰掉了很多手工产品。本质是什么,重复的工作交给了机器去完成。

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。

在这里插入图片描述
在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。

如何证明呢?
看图(稍微懂一点反汇编就行):
在这里插入图片描述
右侧的反汇编中,交换int和交换double的函数地址是不一样的。

其实也可以对应到活字印刷术当中,我们想要有一份文章的拷贝,不是用活字印刷里面的木头块来读的,而是通过那些木头块来把文章印到纸上来读的。

所以上面的就很好理解了,不是用模板,而是用模板来实例化出对应的函数来使用。

其实,C++标准库中也是有交换的函数的,只不过用起来是小写swap。
在这里插入图片描述
可以看到,标准库中实现的就是用的模板。
我们可以直接使用:
在这里插入图片描述

函数模板的实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。

  1. 隐式实例化:让编译器根据实参推演模板参数的实际类型
    先给个能跑的例子:编译器自动推演在这里插入图片描述
    再给个跑不了的例子:
    在这里插入图片描述
    出现上面问题的原因是a和d1的类型是不相同的,而模板函数中两个参数的类型是相同的,但是我们偏要生成一个int和double的函数,这样是生成不了的。因为编译器不能决定到底是用int还是用double来实现。编译器就犯难了,只能报错,不然就得背黑锅。

  2. 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

但是我们之前写的函数是可以进行隐式类型转换的。比如说下面这样:
在这里插入图片描述
如果想用模板来实现两个不同类型相加的时候,可用以下方法:
在这里插入图片描述
但是这样非常挫。

可以用下面的显示实例化来实现。

  1. 显示实例化:在函数名后的<>中指定模板参数的实际类型
    在这里插入图片描述
    这个方法在函数模板中不是那么常用,但是在类模板中就非常常用了。
    再给个在函数模板中适用的场景。
    在这里插入图片描述

上面不能直接使用func,因为模板中的T是不确定的。
这时候就要用到<>了。
在这里插入图片描述

当我们同时拥有模板和一个功能相同的加法函数的时候会发生什么?
在这里插入图片描述
会像上面这样,但是上面的写法是很挫的,不建议同时出现功能相同的函数模板。

类模板

类模板的定义格式

template<class T1, class T2, ..., class Tn>
class 类模板名
{// 类内成员定义
};

和函数模板很像。

类模板的是使用场景是什么呢?
我们来写一个简单的类模板。

在这里插入图片描述

如果想将类模板中的的成员函数在类外定义的话,得像这样:
在这里插入图片描述

还要说一点就是模板不支持分离编译。 声明放在.h 定义放在.cpp。
至于为什么的话放到后面深入讲模板的博客中说。

类模板的实例化

在这里插入图片描述
如果不指明T的类型,是会报错的。
那么用类模板的时候就要显示指出T的类型。
在这里插入图片描述

最后再给一个顺序表的例子:

直接把代码给出来:

template<typename T>
class Stack
{
public:Stack(size_t capacity = 4):_data(nullptr),_top(0),_capacity(0){if (capacity > 0){_data = new T[capacity];_top = 0;_capacity = 4;}}~Stack(){delete[] _data;_data = nullptr;_top = _capacity = 0;}void Push(const T& a){if (_capacity == _top){int newcapacity = _capacity == 0 ? 4 : 2 * _capacity;T* newdata = new T[newcapacity];if (_data){memcpy(newdata, _data, sizeof(T) * _capacity);delete[] _data;}_data = newdata;_capacity = newcapacity;}_data[_top] = a;++_top;}void Pop(){assert(_top);--_top;}bool Empty(){return _top == 0;}const T& Top(){return _data[_top - 1];}private:T* _data;size_t _top;size_t _capacity;
};int main()
{Stack<int> s;s.Push(1);s.Push(2);s.Push(3);s.Push(4);s.Push(5);while (!s.Empty()){cout << s.Top() << " ";s.Pop();}cout << endl;return 0;
}

其中最重要的是下面main函数中的Stack<int> s; 这条语句。

到此结束。。。

相关文章:

【C++】模板的一点简单介绍

模板 前言泛型编程函数模板概念格式函数模板的原理函数模板的实例化 类模板类模板的定义格式类模板的实例化 前言 这篇博客讲的是模板的一些基本知识&#xff0c;并没有那么深入&#xff0c;但是如果你是为了过期末考试而搜的这篇博客&#xff0c;我觉得下面讲的是够了的。 之…...

SpringCloud概述

前言 什么是微服务&#xff1f; ​ 微服务是一种面向服务的架构(SOA)风格&#xff0c;其中&#xff0c;应用程序被构建为多个不同的小型服务的集合而不是单个应用程序。与单个程序不同的是&#xff0c;微服务让你可以同时运行多个独立的应用程序&#xff0c;而这些独立的应用…...

Metal入门学习:GPU并行计算大数组相加

一、编程指南PDF下载链接(中英文档&#xff09; 1、Metal编程指南PDF链接 https://github.com/dennie-lee/ios_tech_record/raw/main/Metal学习PDF/Metal 编程指南.pdf 2、Metal着色语言(Metal Shader Language:简称MSL)编程指南PDF链接 https://github.com/dennie-lee/ios_te…...

关于在spyder,jupyter notebook下创建虚拟环境(pytorch,tensorflow)均有效

anaconda下载地址 https://www.anaconda.com/download/ 下载完成后打开anaconda目录下的 anaconda prompt 在命令行中输入下面的命令创建一个叫tf2.0的虚拟环境&#xff08;“tf2.0”是建立的Conda虚拟环境的名字&#xff0c;可以自拟&#xff09; conda create -n tf2.0 p…...

oracle 闪回恢复

oracle 闪回恢复 闪回恢复区主要通过3个初始化参数来设置和管理&#xff1a; db_recovery_file_dest&#xff1a;指定闪回恢复区的位置 db_recovery_file_dest_size&#xff1a;指定闪回恢复区的可用空间大小 db_flashback_retention_target&#xff1a;指定数据库可以回退的时…...

LeetCode 322 零钱兑换

题目&#xff1a; 给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff0c;返回 -1 。你可以认为每种硬币的数量…...

面试篇SpringMVC是什么以及工作原理

1&#xff0c;什么是SpringMVC呢&#xff1f; 它是Spring的一种设计模式&#xff0c;一款框架。 2&#xff0c;MVC分别代表什么&#xff1f; M代表模型即model的缩写&#xff0c;指业务逻辑层模型。V代表视图即View的缩写&#xff0c;指视图层。C则是controller的缩写&#xff…...

jQuery-层级选择器

<!DOCTYPE HTML> <html> <head> <meta http-equiv"Content-Type" content"text/html; charsetUTF-8"> <title>层级选择器</title> <style type"text/css"> …...

【Java数据结构】——第十节(下).选择排序与堆排序

作者简介&#xff1a;大家好&#xff0c;我是未央&#xff1b; 博客首页&#xff1a;未央.303 系列专栏&#xff1a;Java初阶数据结构 每日一句&#xff1a;人的一生&#xff0c;可以有所作为的时机只有一次&#xff0c;那就是现在&#xff01;&#xff01;&#xff01; 文章目…...

45道SQL题目陆续更新

文章目录 学习视频配置环境第一天内连接 外连接第二天第三天 学习视频 学习视频 配置环境 四张表 配置四张表的sql语句 #创建发据库 create database frogdata charsetutf8&#xff1b;use frogdata;# 学生表 Student create table Student( SId varchar(10), Sname var…...

在线PS软件有哪些不错的推荐

许多新的UI设计合作伙伴非常关心在线ps工具的选择。现在市场上有各种各样的ps网页替代工具&#xff0c;数量众多&#xff0c;令人眼花缭乱。本文简要介绍了10个在线PS工具&#xff0c;我相信一定有一个适合你&#xff01; 1.即时设计 即时设计是一款在线 UI 设计工具&#xf…...

Java实现天气预报功能

如果要实现类似百度天气、手机App这样的天气预报功能该如何实现&#xff1f;首先想到的是百度... 背景&#xff1a; 最近公司做了一个项目&#xff0c;天气预报的功能也做上去了&#xff0c;不仅有实时天气、未来7天预报的功能、还有气象预警的功能。 天气包括基本天气、白天夜…...

python循环语句

while循环 Python中&#xff0c;while循环只要在条件&#xff08;表达式&#xff09;为真的情况下&#xff0c;就会一直重复执行相应的循环代码块。 while语句的语法格式如下&#xff1a; while 条件表达式&#xff1a;代码块while语句执行的具体流程为&#xff1a;首先判断…...

多线程基础(一)线程基础信息、synchronized 锁概念

1. 基本概念&#xff1a; 程序&#xff1a; 程序是一些保存在磁盘上的指令的有序集合&#xff0c;是静态的。程序包括&#xff1a;内存资源、IO资源、信号处理等。&#xff08;如&#xff1a;XX.exe&#xff09; 进程&#xff1a; 进程是程序执行的过程&#xff0c;包括了动态…...

JAVA期末考内容知识点的梳理

作者的话 前言&#xff1a;这些都是很基本的&#xff0c;还有很多没有写出来&#xff0c;重点在于考试复习&#xff0c;包括后四章的内容 前面内容请参考JAVA阶段考内容知识点的梳理 一、集合、流 课堂总结1集合 集合概念&#xff1a; 保存和盛装数据的容器&#xff0c;将许多…...

为什么要使用Thrift与Protocol Buffers?

编码数据的格式 程序通常&#xff08;至少&#xff09;使用两种形式的数据&#xff1a; 在内存中&#xff0c;数据保存在对象、结构体、列表、数组、散列表、树等中。 这些数据结构针对 CPU 的高效访问和操作进行了优化&#xff08;通常使用指针&#xff09;。如果要将数据写…...

oa是什么意思?oa系统哪个好用?

一、oa是什么意思 oa&#xff08;Office Automation办公自动化&#xff09;是一种将智能化科技应用于企业管理中的应用系统。它可以通过电脑网络、互联网等技术手段&#xff0c;将企业的各种业务流程、各种业务数据进行集成和处理&#xff0c;将各种业务流程和各种业务数据统一…...

Linq和C# Lambda表达式

什么是Linq 简介 Linq (Language Integrated Query) 是一种语言集成的查询技术&#xff0c;可以在C#和其他.NET语言中使用。Linq允许我们使用一种类SQL的语言来查询数据&#xff0c;这使得代码更加简洁和易于阅读。Linq提供了一种通用的查询接口&#xff0c;可以用于查询各种…...

蓝桥:前端开发笔面必刷题——Day2 数组(三)

文章目录 &#x1f4cb;前言&#x1f3af;两数之和 II&#x1f4da;题目内容✅解答 &#x1f3af;移除元素&#x1f4da;题目内容✅解答 &#x1f3af;有序数组的平方&#x1f4da;题目内容✅解答 &#x1f3af;三数之和&#x1f4da;题目内容✅解答 &#x1f4dd;最后 &#x…...

人工智能专栏第四讲——人工智能的未来展望与机遇

目录 一、人工智能的未来展望 二、人工智能在各领域的应用 三、人工智能的机遇 四、总结...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

前端倒计时误差!

提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)

升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点&#xff0c;但无自动故障转移能力&#xff0c;Master宕机后需人工切换&#xff0c;期间消息可能无法读取。Slave仅存储数据&#xff0c;无法主动升级为Master响应请求&#xff…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...