C++模板初阶
1.函数模板
模板是C++中一个非常重要的东西,也是下一步学stl的最后一块拼图。那看看最后一块拼图是什么呢?C++祖师爷在写C语言时遇到了有个非常难受的地方:
遇到有很多类型变量交换的时候就要写不同的交换函数,再新增类型的交换还要继续写交换函数,这样就比较繁琐,那有什么好办法吗?这里引入一个小话题:比如有一天我们知道自己要穿越到古代了,穿越到古代的时候可以带现代的东西回去,我们已经提前知道我们穿越回去的工作就是刻字,每天把别人写好的文章刻在石板上为了将文章传出去,那此时我们最想带回去的就是造纸术和活字印刷术,这样可以大大提高效率。那同理祖师爷也就想我们能不能像活字印刷术一样写个模具,需要什么直接印出来就行,所以就有了新语法--模板。模板就像模具,它在这会搞出两个东西,一个叫函数模板,一个叫类模板。
先看看函数模板:
这里要新学一个关键字叫template,他后面跟一个尖括号,因为上面三个交换函数逻辑相同,参数类型不同,所以在尖括号里定义个类型,可以给typename,它是来定义模板参数的关键字,也可以给class,现阶段认为它们是一样的。类型可以叫T/Tp等都可以,名字随意起,日常更喜欢叫T,有type的意思。定义好了T类型,就可以在Swap里面用了,下面写好函数逻辑,这就是一个函数模板。这里面的T是什么具体类型我们不知道,我们只知道它是一个类型。模板厉害的地方是我们不需要写上面三个函数了,只要交换两个变量就可以用上面的函数模板:
用模板和用普通函数一样,只是模板里面类型定义成了模板参数。函数模板和普通函数不一样,函数的参数定义的是变量,是对象,函数模板定义的是类型。那上图两个Swap调的是不是同一个函数呢?不是的,就如同在古代把文章用模具印了很多份出来,老百姓看的文章不是模具,而看的是模具印刷出的复制品。
调式的时候按F11进去看似进了模板,实际不是,这里做了优化,可通过汇编来验证:
那怎么做到看起来调同一个函数实际不是同一个呢?这里其实调的是模板生成的具体函数:
这个过程叫函数模板的实例化。我们在用模板调用时编译器会自动推,如上图传了两个double,推出T是double,然后生成一份T是double的代码;再如传了两个int,推出T是int,然后生成一份T是int的代码。根据参数推出参数T是什么,然后生成对应的代码叫模板的实例化。模板的实例化指用模板生成对应的函数,所以它在这调用的还是生成的函数。因此实际上调用的不是模板,是模板实例化生成的函数,函数是编译器生成的,最终还是编译器承担了一切。这里假设有两个日期类对象也是可以用模板交换的:
这会推出T是Date,然后实例化出交换Date的函数,里面调用拷贝构造和赋值来完成交换。以后再有类似Swap的情况,就不需依次写具体函数,写函数模板就行,这个模板是给编译器用的。其实从此以后不用自己写Swap模板,因为库里面有:
以后想交换直接用就可以,只不过是小写的swap:
可以发现指针交换也不用自己写模板,可以直接用,T可实例化为int*。那不是以前说交换int*要用int**吗,那是C语言的玩法,C++这里有引用,函数形参是实参的别名。
有些地方把用模板完成的东西叫泛型编程,那什么是泛型编程呢?就是我们写的代码是针对广泛的类型,不是针对某种具体的类型。前面main函数里完成a和b的交换,调的不是模板,实际调用的是编译器用函数模板实例化生成的具体函数,也就是交换就要写多个函数,只是模板这个玩法把本来应该由我们干的活交给编译器去做。那能不能定义多个模板参数呢?也是可以的,比如说这里假设有打印不同类型数据的需求:
此时就可以定义多个模板参数,T1推为int,T2推为double,实例化出in和double的函数。前面都用模板类型做参数,也可以用模板类型做返回值:
函数模板根据调用,自己推导模板参数的类型,实例化出对应函数。
下一个要看的是函数模板的实例化,函数模板的实例化有两种方式:第一种叫隐式实例化,也就是编译器根据类型自己去推;第二种叫显示实例化。
上图就是隐式实例化,只有一个模板参数,一个推为int,一个推为double。但有些地方推不了:
如果出现上图这样的方式会出现什么问题呢?这时a1让T推为int,d1让T推为double,那到底推为什么呢?这时编译器就为难了,报错说模板参数T不明确。那怎么解决这样的问题呢?一种方式是让它们达成一致:
用强制类型转化,要么都听a1的转化为int,要么都听d1的转化为double,这样就不存在歧义了。还有一种方式是显示实例化:
隐式实例化是通过实参传递的类型来推演T的类型,显示实例化是用指定的类型实例化,上图第一个就是指定实例化为int,第二个就是指定实例化为double。在函数名和参数之间加尖括号就叫显示实例化,如第一个指定T为int时d1会涉及到隐式类型转化。其实大多数场景下都用不上显示实例化,一般自动推就行,但有一种场景需要用显示实例化,假设有这样一个函数:
这个函数如果不用显示实例化无法使用,用Alloc(10)直接调用都没法推,所以就只能Alloc<double>(10)像这样显示实例化,这里就是有些函数无法自动推,只能显示实例化。
2.类模板
比如我们有了类和对象,我们写一个栈,能不能写一个库出来呢?不能,因为这的类型还是写死的。有时候觉得写的这个东西还可以,想让栈存int就把DataType前写为int,想让栈存double就把DataType前改为double就可以了,这样没什么问题。但有没有可能有这样一个场景:
在同一个程序中我的栈s1要存int,栈s2要存double,此时就不可以了,除非写StackInt和StackDouble两个类,但这样太麻烦。上面这些栈无非就是类型不同,所以一个程序中要不同类型的类,我们不想自己写太多的类,那就交给编译器去完成,给编译器一个模板,这个模板叫类模板:
用的地方不能直接Stack s1这样传参数告诉编译器说用int,因为构造函数这不一定用T参数,所以没法通过推演实例化,所以用类模板要显示实例化。如果有需求类模板也是可以定义多个模板参数的:
最后要说的一个东西是类模板函数声明和定义分离是有些不一样的,如构造函数实现声明和定义分离:
类里面声明,类外面定义,发现按照传统方式声明和定义分离是编不过的,类里面用T知道是的模板参数,类外面不知道T是哪里来的,Stack::Stack(size_t capacity)还是不认识T,所以要声明模板参数。声明后还是不可以,这里有个要注意的地方,类模板和以前有个不一样的地方是:以前对于普通类而言,类名就是类型。对于类模板,类名和类型不一样,如这里Stack是类名,类型是Stack<T>。就比如main中有Stack<int> s1,这里模板实例化出的是Stack<int>类型,如果直接Stack::Stack(size_t capacity)就相当于还没有实力化。类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。因此要这样写:
再比如把Push分离写:
相关文章:
C++模板初阶
1.函数模板 模板是C中一个非常重要的东西,也是下一步学stl的最后一块拼图。那看看最后一块拼图是什么呢?C祖师爷在写C语言时遇到了有个非常难受的地方: 遇到有很多类型变量交换的时候就要写不同的交换函数,再新增类型的交换还要…...
第六章:6.3求一个3*3的整型矩阵对角线元素之和
//求一个3*3的整型矩阵对角线元素之和 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> int main() {int i 0, j 0;int arr[3][3] { 0 };printf("请输入一个3*3的矩阵:\n");for (i 0; i < 3; i){for (j 0; j < 3; j){scanf("%d", …...
Oracle 19c部署之初始化实例(三)
上一篇文章中,我们已经完成了数据库软件安装,接下来我们需要进行实例初始化工作。 一、初始化实例的两种方式 1.1 图形化初始化实例 描述:图形化初始化实例是通过Oracle的Database Configuration Assistant (DBCA)工具完成的。用户通过一系…...
RAGFlowwindows本地pycharm运行
Python环境准备 1. 安装pipx。如已经安装,可跳过本步骤: python -m pip install --user pipxpython -m pipx ensurepath## 验证安装pipx --version2. 安装 uv。如已经安装,可跳过本步骤: pipx install uv ## 设置为阿里云 PyPI…...
阿里云RAM账号免密登录Java最佳实践
参考官方文章地址:如何使用免登访问流程_阿里云集成转售解决方案-阿里云帮助中心 参考代码地址:如何使用安全访问服务Python及Java示例代码_阿里云集成转售解决方案-阿里云帮助中心 1. RAM的含义 阿里云的访问控制RAM(Resource Access Manag…...
基于LightRAG进行本地RAG部署(包括单卡多卡本地模型部署、调用阿里云或DeepSeekAPI的部署方法、RAG使用方法)
1.简介 RAG(Retrieval-Augmented Generation)是一种结合了检索(Retrieval)和生成(Generation)的自然语言处理模型架构。它旨在解决传统生成模型在面对复杂任务时可能出现的生成内容缺乏准确性和多样性的不…...
GPIO输出模式
这个 typedef enum 是 STM32 中 GPIO 模式的定义,每一个模式都代表着 GPIO 引脚的不同工作方式。不同的模式会影响引脚的输入或输出状态,以及是否具有其他功能(如外设功能)。接下来,我将详细解释每个模式的作用和如何使…...
Linux,redis数据库安装使用
Redis 非关系型数据库 介绍 安装 主从模式 哨兵模式 集群模式 redis 数据类型/增删改查 redis 持久化 redis 雪崩 击穿 穿透 LAMPredis 数据迁移 git redis 安装部署 1,下载或者上传redis 6.2.14 wget http://download.redis.io/releases/redis-6.2.14.tar.gz …...
3DS 转 STL 全攻略:传统工具与迪威模型网在线转换深度解析
在 3D 建模与 3D 打印的技术领域中,常常会遇到需要将不同格式的文件进行转换的情况。其中,把 3DS 文件转换为 STL 格式是较为常见的操作。3DS 文件作为一种旧版 Autodesk 3D Studio 使用的 3D 图像格式,存储着丰富的信息,包括网格…...
最新Spring Security实战教程(十一)CSRF攻防实战 - 从原理到防护的最佳实践
🌷 古之立大事者,不惟有超世之才,亦必有坚忍不拔之志 🎐 个人CSND主页——Micro麦可乐的博客 🐥《Docker实操教程》专栏以最新的Centos版本为基础进行Docker实操教程,入门到实战 🌺《RabbitMQ》…...
远程医疗系统安全升级:构建抗CC攻击的全方位防护网
随着云计算、大数据和互联网技术的不断发展,远程医疗系统正在逐步走进大众视野,为患者提供便捷高效的医疗服务。然而,远程医疗系统在便利性的背后也面临着严峻的网络安全挑战,其中,CC攻击(Challenge Collap…...
【Java学习笔记】进制与进制转换
进制与进制转换 一、进制介绍 二进制:0、1,满 2 进 1,以 0b 或 0B 开头。 十进制:0-9,满 10 进 1。 八进制:0-7,满 8 进 1,以数字 0 开头表示。 十六进制:0-9 及 A(10…...
《SpringBoot中@Scheduled和Quartz的区别是什么?分布式定时任务框架选型实战》
🌟 大家好,我是摘星! 🌟 今天为大家带来的是Scheduled和Quartz对比分析: 新手常见困惑: 刚学SpringBoot时,我发现用Scheduled写定时任务特别简单。但当我看到同事在项目里用Quartz时&…...
RestSharp和Newtonsoft.Json结合发送和解析http
1.下载RestSharp和Newtonsoft.Json 2编写ApiRequest和ApiResponse和调用工具类HttpRestClient 请求模型 /// <summary>/// 请求模型/// </summary>public class ApiRequest{/// <summary>/// 请求地址/api路由地址/// </summary>public string Route {…...
[图论]Kruskal
Kruskal 本质:贪心,对边进行操作。存储结构:边集数组。适用对象:可为负权图,可求最大生成树。核心思想:最短的边一定在最小生成树(MST)上,对最短的边进行贪心。算法流程:对全体边集…...
腾讯云对象存储以及项目业务头像上传
腾讯云上传步骤: service-vod模块化中 ①、参考文档,引入依赖 ②、配置文件application.properties ③、创建工具类 初始化bean的时候读取配置文件 Component public class ConstantPropertiesUtil implements InitializingBean{Value("${t…...
Windows下导入文件中的环境变量
在Windows批处理脚本(.bat)中,通过文件获取并设置环境变量通常涉及逐行读取文件内容并动态赋值给变量。以下是具体实现方法及示例: 一、从文件读取变量并设置到环境变量 假设有一个配置文件(如env_config.txt…...
【音视频开发】第五章 FFmpeg基础
【音视频开发】第五章 FFmpeg基础 文章目录 【音视频开发】第五章 FFmpeg基础一、播放器框架1.媒体文件读取阶段2.音频处理流程3.视频处理流程 二、常用音视频概念1.常用音视频术语2.复用器3.编解码器 三、FFmpeg 库1.整体结构 四、FFmpeg 常用函数1.libavformat 封装/解封装2.…...
【ESP32|音频】一文读懂WAV音频文件格式【详解】
简介 最近在学习I2S音频相关内容,无可避免会涉及到关于音频格式的内容,所以刚开始接触的时候有点一头雾水,后面了解了下WAV相关内容,大致能够看懂wav音频格式是怎么样的了。本文主要为后面ESP32 I2S音频系列文章做铺垫࿰…...
数据通信学习笔记之OSPF路由汇总
区域间路由汇总 路由汇总又被称为路由聚合,即是将一组前缀相同的路由汇聚成一条路由,从而达到减小路由表规模以及优化设备资源利用率的目的,我们把汇聚之前的这组路由称为精细路由或明细路由,把汇聚之后的这条路由称为汇总路由或…...
【C++】priority_queue的底层封装和实现
目录 前言基本结构如何设置默认大小堆底层实现仿函数的使用向上调整算法向下调整算法其他接口 end 前言 priority_queue的介绍 优先级队列默认使用vector作为其底层存储数据的容器,在vector上又使用了堆算法将vector中的元素构造成堆的结构,因此priorit…...
2023年全国青少年信息素养大赛 Python编程挑战赛 小学全年级组 初赛真题答案详细解析
2023信息素养大赛 Python编程挑战赛 选择题(共15题,每题5分,共75分) 1、关于列表的索引,下列说法正确的是 A、列表的索引从0开始 B、列表的索引从1开始 C、列表中可能存在两个元素的索引一致 D、列表中索引的最大…...
十三种通信接口芯片——《器件手册--通信接口芯片》
目录 通信接口芯片 简述 基本功能 常见类型 应用场景 详尽阐述 1 RS485/RS422芯片 1. RS485和RS422标准 2. 芯片功能 3. 典型芯片及特点 4. 应用场景 5. 设计注意事项 6. 选型建议 2 RS232芯片 1. RS232标准 2. 芯片功能 3. 典型芯片及特点 4. 应用场景 5. 设计注意事项 6…...
PyTorch生成式人工智能实战(1)——神经网络与模型训练过程详解
PyTorch生成式人工智能实战(1)——神经网络与模型训练过程详解 0. 前言1. 传统机器学习与人工智能2. 人工神经网络基础2.1 人工神经网络组成2.2 神经网络的训练 3. 前向传播3.1 计算隐藏层值3.2 执行非线性激活3.3 计算输出层值3.4 计算损失值3.5 实现前…...
【软件系统架构】事件驱动架构
一、引言 在当今的软件开发和系统架构领域,事件驱动架构(Event - Driven Architecture,EDA)正逐渐成为构建复杂、分布式和可扩展系统的热门选择。随着信息技术的不断发展,传统的架构模式在应对高并发、实时性要求高、数…...
Doris FE 常见问题与处理指南
在数据仓库领域,Apache Doris 凭借其卓越性能与便捷性被广泛应用。其中,FE(Frontend)作为核心组件,承担着接收查询请求、管理元数据等关键任务。然而,在实际使用中,FE 难免会遭遇各类问题&#…...
Manus AI “算法-数据-工程“三位一体的创新
Manus AI在多语言手写识别领域的技术突破,通过算法创新、数据工程与场景适配的协同作用,解决了传统手写识别的核心痛点。以下是其关键技术路径与创新点的系统性分析: 一、深度学习模型与算法优化 混合神经网络架构Manus AI采用"CNN与LST…...
Flutter Expanded 与 Flexible 详解
目录 1. 引言 2. Expanded 的基本用法 3. Flexible 的基本用法 4. Expanded vs Flexible 的区别 4.1 基础定义 4.2 关键差异 5. Expanded 深度解析 5.1 按比例分配 5.2 强制填充特性 6. Flexible 深度解析 6.1 基础用法:动态收缩 6.2 结合 fit 参数控制…...
乘用车制动系统设计:保障行车安全的核心技术
摘要 随着汽车工业的快速发展,乘用车制动系统的设计至关重要。本文详细阐述了乘用车制动系统的工作原理、组成部分、常见类型,深入分析了制动系统设计过程中的关键要点,包括制动力分配、制动管路设计、制动助力系统选型等。同时,…...
电力行业在保障用电安全方面正积极采用先进的物联网技术
电力行业在保障用电安全方面正积极采用先进的物联网技术 电力行业的物联网安全用电监管装置正发挥着至关重要的作用。 ASCO 电不着安全用电装置凭借其卓越的性能,成为了解决用电安全问题的得力助手。 当电漏电这种危险情况悄然发生时,物联网 ASCO 电不着…...
TDengine 语言连接器(PHP)
简介 PHP 语言广泛用于 Web 开发的开源脚本语言。它语法简单,容易学习,既支持面向过程,也支持面向对象编程。具有跨平台性,能与多种数据库交互,可与 HTML 等前端技术配合,动态生成网页内容。常用于开发各类…...
使用docker该怎么做:从公有仓库拉取镜像并上传到私有仓库
在容器化部署中,将公有镜像仓库(如Docker Hub)的镜像迁移到私有仓库(如Harbor、Nexus)是常见需求。 一、为什么需要将镜像从公有仓库传到私有仓库? 网络连通性:公有仓库依赖公网访问ÿ…...
list的使用
1:list文档 list文档 在之前我们对于链表有过最初始的模拟实现,现在进入C之后,我们可以在STL库中发现到链表这个容器的使用,list的底层也是我们最初实现的双向链表。 2:list的使用 list的接口有很多,我们…...
Redis遇到Hash冲突怎么办
在 Redis 中,哈希冲突通常是指当多个键的哈希值相同或位于相同的哈希槽中时发生冲突。Redis 通过底层的哈希表和一些冲突解决机制(如开放地址法、链表法等)来处理哈希冲突问题。这些通常是透明的,作为开发者,我们无需直…...
OpenCV 图形API(42)颜色空间转换-----将 BGR图像转换为 I420(YUV 4:2:0)格式函数BGR2I420()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 将图像从BGR色彩空间转换为I420色彩空间。 该函数将输入图像从BGR色彩空间转换为I420。R、G和B通道值的传统范围是0到255。 输出图像必须是8位无…...
简述Apache RocketMQ
整体架构分析 基本流程 模块特性 发送消息流程原理分析 同步发送 sync 异步发送 async 直接发送 one-way 主从同步(HA)机制分析 消息投递 持久化机制 RocketMQ的RPC通信 RocketMQ中Remoting通信模块的具体实现 消息的协议涉及与编码解码 消…...
AI融合SEO关键词实战指南
内容概要 随着人工智能技术的迭代升级,SEO关键词策略正经历从人工经验驱动向数据智能驱动的范式转变。本指南聚焦AI技术在搜索引擎优化中的系统性应用,通过构建多层技术框架实现关键词全生命周期管理。核心方法论涵盖语义分析引擎的构建原理、基于NLP的…...
RK3588 实现音视频对讲
RK3588 实现音视频对讲方案 RK3588是瑞芯微推出的一款高性能处理器,非常适合用于音视频对讲系统的开发。以下是基于RK3588实现音视频对讲的方案概述: 硬件架构 核心处理器:RK3588 (4xCortex-A76 4xCortex-A55)视频处理: 内置8…...
OSPF区域间路由计算
ABR:区域边界路由器,连接两个不同区域的设备就称为ABR(不同厂商不同,定义很模糊) ASBR:自治系统边界路由器,引入了外部路由,将不是自治系统外部的不是OSPF路由的条目变成OSPF路由条目…...
NAT、代理服务、内网穿透
NAT、代理服务、内网穿透 1、NAT1.1、NAT过程1.2、NAPT2、内网穿透3、内网打洞3、代理服务器3.1、正向代理3.2、反向代理1、NAT 1.1、NAT过程 之前我们讨论了IPv4协议中IP地址数量不充足的问题。NAT技术是当前解决IP地址不够用的主要手段,是路由器的一个重要功能。 NAT能够将…...
阿尔特拉 EP1C12F324I7N AlteraFPGA Cyclone
EP1C12F324I7N 属于 Altera Cyclone I 系列 FPGA 中的中低密度型号,面向成本敏感、功耗受限的嵌入式与数据通路应用。该器件采用 0.13 μm 全层铜 SRAM 工艺,集成约 12 060 个逻辑单元(LE)、239 616 位片上 RAM、249 路可编…...
解决“驱动程序无法通过使用安全套接字层(SSL)加密与 SQL Server 建立安全连接“问题
参考链接: https://blog.csdn.net/yyj12138/article/details/123073146...
QtApplets-实现应用程序单例模式,防止重复运行
QtApplets-实现应用程序单例模式,防止重复运行 文章目录 QtApplets-实现应用程序单例模式,防止重复运行摘要引言实现原理核心代码实现头文件定义实现文件 使用方法技术要点解析1. 文件锁机制2. 进程 ID 管理3. Windows 互斥量4. 跨平台兼容 注意事项…...
nodejs使用pkg打包文件
pkg配置 "pkg": {"assets": ["*.html","*.css","*.js"],"mirror": "https://npmmirror.com/mirrors/node-v8-compile-cache/"},"bin": "server.js",嵌入到exe中的资源使用assets打…...
学习笔记十六——Rust Monad从头学
🧠 零基础也能懂的 Rust Monad:逐步拆解 三大定律通俗讲解 实战技巧 📣 第一部分:Monad 是什么? Monad 是一种“包值 链操作 保持结构”的代码模式,用来处理带上下文的值,并方便连续处理。 …...
Idea连接远程云服务器上的MySQL,开放云服务器端口
1.开放云服务器的3306端口 (1)进入到云服务器的控制台 (2)点击使用的云服务器 (3)点击 配置安全组规则 (4)添加规则 (5)开放端口 2.创建可以远程访问…...
云服务器CVM标准型S5实例性能测评——2025腾讯云
腾讯云服务器CVM标准型S5实例具有稳定的计算性能,CPU采用采用 Intel Xeon Cascade Lake 或者 Intel Xeon Cooper Lake 处理器,主频2.5GHz,睿频3.1GHz,CPU内存配置2核2G、2核4G、4核8G、8核16G等配置,公网带宽可选1M、3…...
【Pytorch之一】--torch.stack()方法详解
torch.stack方法详解 pytorch官网注释 Parameters tensors:张量序列,也就是要进行stack操作的对象们,可以有很多个张量。 dim:按照dim的方式对这些张量进行stack操作,也就是你要按照哪种堆叠方式对张量进行堆叠。dim的…...
监控+日志=DevOps 运维的“千里眼”与“顺风耳”
监控+日志=DevOps 运维的“千里眼”与“顺风耳” 在 DevOps 体系中,监控和日志管理是不可或缺的运维基石。有人说,开发只管把代码写好,运维才是真正的“操盘手”,让系统稳定运行、不宕机、不崩溃。而要做到这一点,精准的监控与日志管理 是关键。 试想一下:如果没有监控…...
实战|使用环信Flutter SDK构建鸿蒙HarmonyOS应用及推送配置
本文为大家介绍如何在 Flutter 环境创建 Harmony 项目并集成环信即时通讯IM以及环信 Flutter Harmony 推送配置。 已经基于环信的 Flutter 项目也可以参考本文适配鸿蒙端。 一、开发环境要求 前置条件 1.安装DevEco-Studio 2.安装模拟器 DevEco-Studio 下载与操作指导&…...