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

重生之从0开始学习c++之模板初级

1. 泛型编程 —— 为什么需要模板如何实现一个通用的交换函数呢voidSwap(intleft,intright){inttempleft;leftright;righttemp;}voidSwap(doubleleft,doubleright){doubletempleft;leftright;righttemp;}voidSwap(charleft,charright){chartempleft;leftright;righttemp;}因为c支持函数重载所以如果我们想用不同类型的参数是不是可以这么写啊但是这样写是不是有点麻烦和冗余啊因为它们的逻辑完全相同仅仅是类型不同。那能否告诉编译器一个模子让编译器根据不同的类型利用该模子来生成代码呢就像这样┌─────────────────────────────────────────────────────────────┐ │ 模具(模板)│ │ ┌─────────────────────────────────────────────────────┐ │ │ │ │ │ │ │voidSwap(Tleft,Tright)│ │ │ │{│ │ │ │ T templeft;│ │ │ │ leftright;│ │ │ │ righttemp;│ │ │ │}│ │ │ │ │ │ │ └─────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────┘ │ │ │ ▼ 倒入绿色液体 ▼ 倒入蓝色液体 ▼ 倒入红色液体 ┌─────────┐ ┌─────────┐ ┌─────────┐ │ Swap │ │ Swap │ │ Swap │ │int│ │double│ │char│ └─────────┘ └─────────┘ └─────────┘如果在C中也能够存在这样一个模具通过给这个模具中填充不同材料(类型)来获得不同材料的铸件(即生成具体类型的代码那将会节省许多头发。巧的是前人早已将树栽好我们只需在此乘凉。核心思想泛型编程——编写与类型无关的通用代码由编译器根据实际使用时的类型自动生成针对该类型的代码。2. 函数模板函数模板代表了一个函数家族该函数模板与类型无关在使用时被参数化根据实参类型产生函数的特定类型版本。2.1 函数模板的语法templatetypename T1, typename T2,…,typename Tn返回值类型 函数名(参数列表){}templatetypenameT// T 是模板参数可以是 typename 或 classvoidSwap(Tleft,Tright){T templeft;leftright;righttemp;}2.2 函数模板的原理函数模板本身不是函数它只是一个蓝图。编译器遇到函数模板的调用时才会根据实参类型生成一个具体的函数。这个过程叫做模板实例化。流程图解编译器在编译期的推演过程源代码 ─────────────────────────────────────────────────────────────intmain(){doubled12.0,d25.0;Swap(d1,d2);// 调用点1inti110,i220;Swap(i1,i2);// 调用点2chara0,b9;Swap(a,b);// 调用点3}───────────────────────────────────────────────────────────── │ │ │ ▼ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ 编译器推演 │ │ 编译器推演 │ │ 编译器推演 │ │ 实参类型double│ │ 实参类型int│ │ 实参类型char│ │ 推导 Tdouble│ │ 推导 Tint│ │ 推导 Tchar│ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ ▼ ▼ ▼ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ 生成的函数 │ │ 生成的函数 │ │ 生成的函数 │ │voidSwap(│ │voidSwap(│ │voidSwap(│ │doubleleft,│ │intleft,│ │charleft,│ │doubleright │ │intright)│ │charright)│ │){...}│ │{...}│ │{...}│ └─────────────────┘ └─────────────────┘ └─────────────────┘编译器为每种不同的类型组合生成一份独立的函数代码。最终的可执行文件中包含了Swapdouble、Swapint、Swapchar三个具体的函数就像你手动写了三个重载一样。2.3 函数模板的实例化用具体类型使用函数模板称为实例化。分为两种隐式实例化让编译器自动根据实参类型推导模板参数。templateclassTTAdd(constTleft,constTright){returnleftright;}intmain(){Add(1,2);// 两个实参都是 int推导 T intAdd(1.0,2.0);// 两个实参都是 double推导 T double// Add(1, 2.0); // 编译错误一个 int一个 double编译器推导冲突}错误图解调用Add(1,2.0) │ ├─ 实参1(1)类型为int→ 推导 Tint├─ 实参2(2.0)类型为double→ 推导 Tdouble│ └─ 冲突模板参数列表中只有一个 T编译器无法确定 T 到底是int还是double。 编译器不会进行隐式类型转换因为转换可能丢失数据编译器不背这个锅。解决方案Add(a,(int)d);// 方案1用户手动强转Addint(a,d);// 方案2显式实例化推荐显式实例化在函数名后用 类型 强制指定模板参数。Addint(10,20.0);// 强制 T int20.0 会被隐式转换为 int流程图调用Addint(a,b) │ ▼ ┌─────────────────────────────────────────┐ │ 编译器用户已指定 Tint不用推导了 │ │ 实参a(int)→ 匹配 │ │ 实参b(double)→ 尝试隐式转换为int│ │ 如果能转就编译通过否则报错 │ └─────────────────────────────────────────┘ │ ▼ 生成函数intAdd(constintleft,constintright)2.4 模板参数的匹配原则原则一非模板函数可以和同名模板函数共存// 非模板函数专门处理 intintAdd(intleft,intright){returnleftright;}// 模板函数通用版本templateclassTTAdd(T left,T right){returnleftright;}原则二优先调用非模板函数除非模板能生成更好的匹配Add(1,2);// 调用非模板函数完全匹配且非模板优先Addint(1,2);// 强制调用模板实例化的版本Add(1,2.0);// 非模板不匹配参数类型不同模板可以生成更好的匹配如果模板有两个参数决策流程图遇到函数调用Add(1,2) │ ├─ 查找同名非模板函数 → 找到intAdd(int,int)→ 完全匹配 → 调用 │ └─ 即使模板能生成完全相同的函数也不考虑非模板优先 遇到函数调用Add(1,2.0) │ ├─ 查找同名非模板函数 →intAdd(int,int)不匹配第二个参数类型不对 │ └─ 查找模板 → 若有templateclassT1,classT2版本可生成匹配函数 → 调用模板实例化版本原则三模板函数不允许自动类型转换普通函数可以voidfunc(intx,inty){}// 普通函数templateclassTvoidfunc(T x,T y){}// 模板函数func(1,a);// 调用普通函数a 自动转换为 intASCII 97// 模板函数不会考虑因为 char 和 int 推导冲突3. 类模板3.1 为什么需要类模板以 Stack栈为例我们需要存储 int 的栈也需要存储 double、string 的栈。如果不用模板要么为每种类型写一个类要么用 void* 或继承不类型安全。类模板就是类的模具。3.2 类模板的定义格式templateclassT1,classT2,...,classTnclass类模板名{// 类内成员定义};我们来举一个我们很熟练的栈的例子templateclassTypeclassStack{public:Stack(intcapacity4):_arr(newType[capacity]),_size(0),_capacity(capacity){}~Stack(){delete[]_arr;_arrnullptr;_size_capacity0;}voidPush(constTypex){if(_capacity_size){Type*tmpnewType[_capacity*2];memcpy(tmp,_arr,sizeof(Type)*_size);delete[]_arr;_arrtmp;_capacity_capacity*2;}_arr[_size]x;}voidPrint()const{for(inti0;i_size;i){cout_arr[i] ;}}private:Type*_arr;int_size;int_capacity;};intmain(){Stackintst1;st1.Push(1);st1.Push(2);st1.Push(3);st1.Push(4);st1.Print();return0;}关键点类模板名字是 Stack但真正的类型是Stackint、Stackdouble等。成员函数在类外定义时必须写成templateclass T void StackT::Push(...)。模板的声明和定义通常不分离到 .h 和 .cpp 两个文件否则会导致链接错误原因涉及模板实例化的编译模型后面会深入。3.3 类模板的实例化类模板必须显式实例化不能像函数模板那样隐式推导。类模板实例化与函数模板实例化不同类模板实例化需要在类模板名字后跟然后将实例化的类型放在中即可类模板名字不是真正的类而实例化的结果才是真正的类。Stackintst1;// 实例化出一个存储 int 的栈类Stackdoublest2;// 实例化出一个存储 double 的栈类程序代码段编译后 ┌───────────────────────────────────────────────────────────┐ │ Stackint类编译器生成 │ │-_array:int*│ │-Push(constint)│ ├───────────────────────────────────────────────────────────┤ │ Stackdouble类编译器生成 │ │-_array:double*│ │-Push(constdouble)│ └───────────────────────────────────────────────────────────┘ ↑ ↑ │ │ 使用 Stackintst1 使用 Stackdoublest2

相关文章:

重生之从0开始学习c++之模板初级

1. 泛型编程 —— 为什么需要模板? 如何实现一个通用的交换函数呢? void Swap(int& left, int& right) { int temp left; left right; right temp; } void Swap(double& left, double& right) { double temp left; left right; rig…...

c++怎么编写多线程安全的跨平台文件日志库_无锁队列与异步IO【附源码】

因为 std::ofstream 不是线程安全的,多个线程同时调用其 write() 等成员函数会引发数据竞争,导致未定义行为、崩溃或日志错乱。为什么直接用 std::ofstream 多线程写日志会崩多个线程同时调用 std::ofstream::write() 或 std::ios_base::failure 异常或进…...

ESP32 BLE蓝牙AT指令实战:跨厂商模块透传配置与避坑指南

1. ESP32 BLE蓝牙透传入门指南 第一次接触ESP32 BLE蓝牙透传的朋友可能会觉得有点懵,其实说白了就是让两个蓝牙设备像对讲机一样自由收发数据。我最近刚用ESP32和亿佰特E104-BT5011A模块完成了这个项目,过程中踩了不少坑,今天就把完整流程和避…...

SAP ECC6 EC-CS 合并报表操作手册(完整版)

SAP ECC6 EC-CS 合并报表操作手册(完整版)适用版本:ECC6.0(含 EHP)模块:EC-CS(Enterprise Controlling – Consolidation)核心用途:法定合并、管理合并、内部交易抵销、股…...

进阶提升!MySQL存储过程、触发器与视图实操指南

前三篇我们依次掌握了MySQL基础CRUD、进阶查询、事务、索引及数据备份,已经能满足日常开发和企业级基础数据操作需求。但在实际工作中,经常会遇到重复执行的SQL操作(如批量处理数据)、需要自动触发的业务逻辑(如数据插…...

# Bug 报告:openai-codex provider broken since 2026.4.5 �� Cloudflare challenge + missing OAuth scope /

Bug 报告:openai-codex provider broken since 2026.4.5 �� Cloudflare challenge + missing OAuth scope / openai-codex provider broken since 2026.4.5 - Cloudflare challenge + missing OAuth scope 链接: https://blog.csdn.net/cosmoslife 作者: cosmoslife 日期: 2…...

共探智能医疗与人工智能的新时代 | IHAI 2026

探索智能医疗与AI的未来 | IHAI 2026 国际会议 地点: 中国玉溪会议简介2026年智能医疗与人工智能国际会议(IHAI 2026)将于本年度在中国玉溪举行。这座融合了自然美景与多元文化的古城将迎来全球智能医疗和人工智能领域的顶尖专家、学者及行业领袖。本次大…...

告别乱码!手把手教你用LvglFontTool为LVGL嵌入式UI制作中文字库(附SPI Flash/SD卡存储方案)

嵌入式UI开发实战:LVGL中文字库高效制作与存储方案全解析 在嵌入式系统开发中,图形用户界面(GUI)的中文显示一直是开发者面临的棘手问题。当你在STM32或ESP32上使用LVGL构建交互界面时,是否遇到过这样的场景:精心设计的界面在显示…...

【硬件】2026最适合做家用NAS的CPU是哪一款

家用NAS没有绝对“唯一最优”的CPU,核心是匹配你的预算、功能需求和功耗预期。结合2026年的市场现状、软件兼容性和实测表现,以下是分场景的精准推荐,覆盖99%的家用需求,同时附上核心选型原则和避坑指南。 核心选型黄金原则&#…...

s2-pro参数调优指南:Max New Tokens与Chunk Length对语音连贯性影响

s2-pro参数调优指南:Max New Tokens与Chunk Length对语音连贯性影响 1. 引言 s2-pro作为Fish Audio开源的专业级语音合成模型镜像,在文本转语音领域表现出色。它不仅支持基础的文本转语音功能,还能通过参考音频复用特定音色,为语…...

告别printf调试:用NRF52832的UART串口实现高效日志输出(附SDK15.3配置)

NRF52832串口日志实战:从printf到高效调试的进阶之路 调试嵌入式系统就像在黑暗房间里找钥匙——传统printf调试如同每次开灯看一眼又关上,而UART日志系统则是装上了智能照明,让问题无处遁形。对于NRF52832这样的低功耗蓝牙芯片开发者来说&am…...

商城小程序,不只是卖货这么简单

在数字化浪潮席卷各行各业的今天,商城小程序早已不是新鲜事物。但真正把商城小程序做深、做透,让它适配千行百业的差异化需求,却并非一件容易的事。我们深耕软件开发多年,发现很多客户对商城小程序的认知还停留在“线上摆个摊”的…...

洛谷 P1381 单词背诵

题目描述灵梦有 n 个单词想要背,但她想通过一篇文章中的一段来记住这些单词。文章由 m 个单词构成,她想在文章中找出连续的一段,其中包含最多的她想要背的单词(重复的只算一个)。并且在背诵的单词量尽量多的情况下&…...

批量归一化基础:让模型训练更稳定

文章目录前言一、没BN的深度学习有多难?先懂痛点再学技术1.1 内部协变量偏移:网络每层都在“乱变”1.2 梯度消失与爆炸:深层网络的“拦路虎”1.3 调参难如登天:对初始化和学习率极度敏感二、批量归一化到底是什么?一句…...

常见网络攻击

DDoS攻击,CC攻击 CC攻击 DDoS的一种 发送大量的合法请求消耗应用层的资源(CPU,内存,数据等),耗尽资源,比如在教务网站中写死循环脚本持续访问某个资源,无技术难度 防御: 对同IP限流,验证码,行为分析 DDoS 全名分布式拒绝攻击,攻击者控制大量僵尸设备(被植入病毒的电脑,服…...

NaViL-9B多模态模型应用:智能识别图片内容,轻松实现图文对话

NaViL-9B多模态模型应用:智能识别图片内容,轻松实现图文对话 1. NaViL-9B模型概述 NaViL-9B是上海人工智能实验室研发的原生多模态大语言模型,具备同时处理文本和图像信息的能力。与传统的单一模态模型不同,NaViL-9B能够理解图片…...

从linspace到logspace:Matlab新手必须掌握的两种‘间距’生成函数对比指南

从linspace到logspace:Matlab新手必须掌握的两种‘间距’生成函数对比指南 刚接触Matlab的工程师或科研人员,常常会被各种数据生成函数弄得眼花缭乱。特别是在需要创建特定间隔的数值序列时,linspace和logspace这两个看似简单的函数&#xff…...

企业级大模型API中转站实测对比:主线、备线怎么排更合理

很多团队做大模型接入时,会先问一个看起来很直接的问题:哪家 API 中转站更强。可只要项目进入正式阶段,你就会发现,这个问题本身问得还不够工程化。更现实的问法通常是:谁适合做主线,谁适合做备线&#xff…...

品牌却从未出现在 AI 搜索回答推荐中

说真的,现在绝大多数品牌在 AI 搜索里拿不到曝光,根本不是内容发的少,也不是全网营销做的不好,是从根上就没搞懂,AI 搜索选内容、推品牌的逻辑,和传统的全网营销,完全是两码事。截至 2025 年 12…...

Flux Sea Studio 性能基准测试:不同GPU型号下的生成速度对比

Flux Sea Studio 性能基准测试:不同GPU型号下的生成速度对比 最近在折腾AI生图,特别是用Flux Sea Studio,发现一个挺实际的问题:选什么GPU?是咬牙上顶配的RTX 4090,还是性价比更高的RTX 3080?它…...

证券行业-股票行情指标模型的简单介绍

在证券行业,股票行情指标模型是连接“数据”与“决策”的桥梁。它不仅仅是看K线,而是通过一套标准化的数学逻辑,将无序的价格波动转化为可执行的交易信号。这些模型主要分为技术分析模型(看图择时)和量化因子模型&…...

2026 最新 从零搭建本地大模型 RAG 知识库问答系统:基于 Llama 3.2 8B 量化版 + LangChain+Chroma,全流程代码实操 + 踩坑指南

2026最新 从零搭建本地大模型RAG知识库问答系统:基于Llama 3.2 8B量化版LangChainChroma,全流程代码实操踩坑指南 【本文首发CSDN,未经授权禁止转载】 文章目录 文章目录2026最新 从零搭建本地大模型RAG知识库问答系统:基于Llam…...

餐饮零售AI视觉助手Ostrakon-VL-8B:开箱即用,一键部署实战

餐饮零售AI视觉助手Ostrakon-VL-8B:开箱即用,一键部署实战 1. 为什么选择Ostrakon-VL-8B? 在餐饮零售行业,每天都有大量视觉数据需要处理:货架商品、门店环境、价格标签等。传统人工检查方式效率低、成本高且容易出错…...

STEP3-VL-10B惊艳效果:手写体+印刷体混合文档端到端识别与语义整合

STEP3-VL-10B惊艳效果:手写体印刷体混合文档端到端识别与语义整合 1. 引言 想象一下,你手头有一份会议记录,上面既有打印的会议议程,又有参会者手写的笔记和批注。或者是一份学生作业,题目是印刷体,答案却…...

一键部署Pi0具身智能:快速体验3.5B参数模型,生成标准机器人控制数据

一键部署Pi0具身智能:快速体验3.5B参数模型,生成标准机器人控制数据 1. Pi0具身智能模型简介 Pi0(π₀)是Physical Intelligence公司开发的视觉-语言-动作(VLA)基础模型,代表了当前具身智能领…...

YOLOv10镜像体验:开箱即用的目标检测环境,省心又高效

YOLOv10镜像体验:开箱即用的目标检测环境,省心又高效 1. 为什么选择YOLOv10镜像 在目标检测领域,环境配置一直是开发者面临的最大痛点之一。我曾经花费整整两天时间调试CUDA版本与PyTorch的兼容性问题,这种经历相信很多同行都深有…...

2026企业文档选型白皮书:功能、技术栈、私有化部署与采购建议

核心结论:企业文档工具市场年复合增长率达46.7%。对于有数据安全、二次开发需求的企业,支持私有化部署源码开放的方案(如JVS企业文档)已成为技术团队的优先选择。本文基于11款主流产品深度评测,提供功能对比矩阵、技术…...

从零搭建个人知识库问答系统:我的 Spring AI + RAG 学习实践

一个基于 Spring AI 和 RAG 技术的个人知识库问答 Agent 项目分享 地址:nestNe/personal-knowledge-rag: 基于SpringAI,通过上传自己的知识库,创建个性化的模型回答问题https://github.com/nestNe/personal-knowledge-rag目前还在开发中&…...

LLM生成代码如何逃过SAST/SCA检测?:一文拆解3层语义级审查盲区与可落地的增强审查Checklist(含YAML模板)

第一章:LLM生成代码如何逃过SAST/SCA检测?:一文拆解3层语义级审查盲区与可落地的增强审查Checklist(含YAML模板) 2026奇点智能技术大会(https://ml-summit.org) 大语言模型生成的代码常在语法合法、结构合规的前提下…...

告别AD7689!用STM32双SPI同步采集,低成本升级到16通道AD7616的实战指南

从AD7689到AD7616:基于STM32双SPI的16通道同步采集系统实战 在工业自动化、医疗设备和测试测量领域,多通道高精度数据采集系统的需求日益增长。许多工程师最初会选择AD7689这类单通道ADC作为解决方案,但随着项目复杂度提升,通道扩…...