C++的模板简介
文章目录
- 一、前言
- 二、函数模板(Function Template)
- 三、类模板(Class Template)
- 四、变参模板(Variadic Template)
- 五、模板的递归与元编程
- 六、模板的局限与陷阱
- 七、常用模板的实例
- 八、C++20 的概念(Concepts)
- 九、总结
一、前言
C++的模板(Template)是C++中一种强大的特性,它允许编写泛型程序,即编写不依赖于具体类型的代码。模板提供了一种机制,可以在编译时生成针对不同数据类型的代码,而不需要重复编写相同逻辑的代码。这种机制使得代码更加灵活和可重用。
二、函数模板(Function Template)
函数模板允许我们编写与具体类型无关的函数,从而使得函数能够处理不同的数据类型。函数模板的语法格式如下:
template<typename T1, typename T2,......,typename Tn>
返回值类型 函数名(参数列表)
{// 函数体
}
注意:typename是用来定义模板参数关键字,也可以使用class(切记:不能使用struct代替class)
template <typename T>
T max(T a, T b) {return (a > b) ? a : b;
}int main() {int x = 10, y = 20;double a = 5.5, b = 2.3;std::cout << max(x, y) << std::endl; // 输出 20std::cout << max(a, b) << std::endl; // 输出 5.5return 0;
}
在这里,typename T 表示模板参数T,它是一个占位符,表示函数中可以使用任意类型。当我们调用这个函数时,编译器会根据传递的参数类型自动推导出T的具体类型。
- 模板类型参数与非类型模板参数
除了类型参数外,C++还支持非类型模板参数。非类型模板参数通常是一个整数或指针值,可以在编译时确定。例如:
template <typename T, int size>
T arraySum(T (&arr)[size]) {T sum = 0;for (int i = 0; i < size; ++i) {sum += arr[i];}return sum;
}
在这个例子中,size 是一个非类型模板参数,表示数组的大小。
- 显式指定模板参数
虽然编译器通常可以推导出模板参数,但也可以显式地指定它们:
int a = max<int>(3, 7);
三、类模板(Class Template)
类模板允许定义一个通用的类,然后可以用不同的数据类型来实例化该类。典型的例子是标准库中的 std::vector 类,它是一个类模板,可以用来存储任意类型的元素。它的语法格式跟类模板类型,下面是一个简单的类模板示例:
template <typename T>
class Pair {
public:Pair(T first, T second) : first_(first), second_(second) {}T getFirst() const { return first_; }T getSecond() const { return second_; }private:T first_, second_;
};int main() {Pair<int> intPair(1, 2);Pair<std::string> stringPair("hello", "world");std::cout << intPair.getFirst() << ", " << intPair.getSecond() << std::endl; // 输出 1, 2std::cout << stringPair.getFirst() << ", " << stringPair.getSecond() << std::endl; // 输出 hello, worldreturn 0;
}
- 模板特化(Template Specialization)
模板特化允许我们为特定类型提供模板的特殊实现。模板特化有两种形式:全特化和部分特化。全特化是为模板的特定类型提供完全不同的实现,下面这个例子实例化Pair< bool >时就会调用特化实现而不是通用实现:
template <typename T>
class Pair {
public:Pair(T first, T second) : first_(first), second_(second) {}T getFirst() const { return first_; }T getSecond() const { return second_; }private:T first_, second_;
};template <>
class Pair<bool> {
public:Pair(bool first, bool second) : bits((first ? 1 : 0) | (second ? 2 : 0)) {}bool getFirst() const { return bits & 1; }bool getSecond() const { return bits & 2; }private:int bits;
};
部分特化只适用于类模板,而不是函数模板,它允许为一部分模板参数提供特定实现:
template <typename T, typename U>
class Pair {
public:Pair(T first, U second) : first_(first), second_(second) {}void print() { std::cout << first_ << ", " << second_ << std::endl; }
private:T first_;U second_;
};// 部分特化版本,针对相同类型的 Pair
template <typename T>
class Pair<T, T> {
public:Pair(T first, T second) : first_(first), second_(second) {}void print() { std::cout << "Matching types: " << first_ << ", " << second_ << std::endl; }
private:T first_;T second_;
};
在这个例子中,当 Pair 的两个模板参数类型相同时,编译器会选择部分特化版本,而不是通用版本。
四、变参模板(Variadic Template)
C++11 引入了变参模板,允许模板接受可变数量的模板参数。这对处理不定数量的参数或类型非常有用。
template<typename... Args>
void print(Args... args) {(std::cout << ... << args) << std::endl;
}
在这个例子中,print函数可以接受任意数量的参数,并将它们打印出来。
五、模板的递归与元编程
模板递归和元编程是一种高级用法,允许在编译时进行复杂的计算和逻辑处理。典型的例子是计算编译时的斐波那契数列:
template<int N>
struct Fibonacci {static const int value = Fibonacci<N-1>::value + Fibonacci<N-2>::value;
};template<>
struct Fibonacci<1> {static const int value = 1;
};template<>
struct Fibonacci<0> {static const int value = 0;
};
这种编译期计算被称为模板元编程(Template Metaprogramming),用于在编译期执行逻辑判断和计算。
六、模板的局限与陷阱
编译时间: 模板实例化会增加编译时间,尤其是对于大型代码库。
代码膨胀: 模板实例化会导致二进制文件膨胀,因为每种类型的实例化都会生成独立的代码。
错误信息复杂: 当模板代码出错时,编译器产生的错误信息通常较为复杂且难以理解。
七、常用模板的实例
STL 是 C++ 标准库的一部分,其中包含了大量的模板,如 std::vector, std::map, std::set 等。这些模板类使得开发者能够方便地使用各种数据结构和算法,而不必为每种类型单独实现。
八、C++20 的概念(Concepts)
C++20 引入了概念(Concepts),使得模板的类型约束更加明确。概念是一种用于限制模板参数的特性,可以显著提高模板代码的可读性和可维护性。
template <typename T>
concept Addable = requires(T a, T b) {{ a + b } -> std::convertible_to<T>;
};template <Addable T>
T add(T a, T b) {return a + b;
}
通过引入概念,编译器可以更早地检测出不满足条件的模板参数,从而减少复杂的编译错误信息。
九、总结
C++模板是一种功能强大且灵活的机制,能够极大地提高代码的复用性和类型安全性。模板的学习曲线较为陡峭,但一旦掌握,它将成为编写高效、通用代码的利器。C++20 的概念进一步增强了模板的表达能力,使得模板编程更加直观和强大。
相关文章:
C++的模板简介
文章目录 一、前言二、函数模板(Function Template)三、类模板(Class Template)四、变参模板(Variadic Template)五、模板的递归与元编程六、模板的局限与陷阱七、常用模板的实例八、C20 的概念(…...

树莓派5 笔记25:第一次启动与配置树莓派5_8G
今日继续学习树莓派5 8G:(Raspberry Pi,简称RPi或RasPi) 本人所用树莓派4B 装载的系统与版本如下: 版本可用命令 (lsb_release -a) 查询: Opencv 与 python 版本如下: 今日购得了树莓派5_8G版本,性能是同运…...

Melittin 蜂毒肽;GIGAVLKVLT TGLPALISWI KRKRQQ
【Melittin 蜂毒肽 简介】 蜂毒肽(Melittin)是蜜蜂毒液中的主要活性成分,由26个氨基酸组成,具有强碱性,易溶于水,是已知抗炎性最强的物质之一。蜂毒肽具有多种生物学、药理学和毒理学作用,包括…...

day32
更新源 cd /etc/apt/ sudo cp sources.list sources.list.save 将原镜像备份 sudo vim sources.list 将原镜像修改成阿里源/清华源,如所述 阿里源 deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiver…...
【clickhouse】 使用 SQLAlchemy 连接 ClickHouse 数据库的完整指南
我听见有人猜 你是敌人潜伏的内线 和你相知多年 我确信对你的了解 你舍命救我画面 一一在眼前浮现 司空见惯了鲜血 你忘记你本是娇娆的红颜 感觉你我彼此都那么依恋 🎵 许嵩《内线》 ClickHouse 是一款非常高效的开源列式数据库,因…...

按键收集单击,双击和长按
按键收集单击,双击和长按 引言 在我们生活中, 按键是必不可少的, 不同的电器, 有不同的按键, 但是按键总有不够用的时候, 那么给与一个按键赋予不同的功能,就必不可少了. 一个按键可以通过按下的时间长短和频次, 来定义其类型。 一次按键收集, 都是在一个按键收集周…...
进程的异常终止
进程的异常终止 进程收到了某些信号,他杀 进程自己调用abort函数,产生了SIGABRT(6)信号,自杀 进程的最后一个线程收到了"取消"操作,并且做出响应 如果进程是异常结束的,atexit\on_exit它们事先注册的遗言…...

并发编程 | Future是如何优化程序性能
在初识Future一文中介绍了Future的核心方法。本文中接着介绍如何用Future优化我们的程序性能。 在此之前,有必要介绍Future接口的一个实现类FutureTask。 FutureTask介绍 FutureTask继承结构 首先我们看一下FutureTask的继承结构: public class Futur…...
Oracle笔记
一、 如何解决 sqlplus 无法使用退格键和方向键 .bashrc 中添加如下内容,解决 退格键 stty erase ^h 安装 rlwap 后,执行如下命令可解决 方向键 rlwap sqlplus 二、 都有哪些备份数据到工具 三、 谈谈 你对 oracle 中实例和数据库的理解 数据库是一…...

LVS+Keepalived 双机热备
LVSKeepalived 双机热备 Keepalived案例分析Keepalived工具介绍Keepalived工具介绍一、功能特点 一、理解Keepalived实现原理实验报告资源列表一、安装keepalived以及ipvsadm Keepalived案例分析 企业应用中,单台服务器承担应用存在单点故障的危险单点故障一旦发生…...

Web Image scr图片从后端API获取基本实现
因系统开发中需求,会有页面显示图片直接从后端获取后显示,代码如下: 后端: /*** 获取图片流* param response* param fileName*/RequestMapping(value"getImgStream",method RequestMethod.GET)public void getImgStr…...

2024音频剪辑指南:探索四大高效工具!
音频剪辑不仅仅是技术活,更是一种艺术创作,它能够让声音更加生动、更具感染力。今天,我们就来探索几款优秀的音频剪辑工具。 福昕音频剪辑 链接:www.pdf365.cn/foxit-clip/ 福昕音频剪辑是一款界面简洁、操作直观的音频编辑软件…...

“CSS”第一步——WEB开发系列13
CSS (Cascading Style Sheets,层叠样式表),是一种用来为结构化文档(如 HTML 文档或 XML 应用)添加样式(字体、间距和颜色等)的计算机语言,CSS 文件扩展名为 .css。 一、什么是 CSS&a…...

IEEE802网络协议和标准
IEEE802网络协议和标准 802委员会IEEE 802介绍现有标准 IEEE 802.3介绍物理媒介类型MAC子层与LLC子层主要内容通讯标准POE供电标准802.3af、802.3at、802.3btIEEE802.3af的工作过程:IEEE802.3af主要供电参数:IEEE802.3af的分级参数:为什么会有…...

vulnhub靶机 DC-9(渗透测试详解)
一、靶机信息收集 1、靶机下载 https://download.vulnhub.com/dc/DC-9.zip 2、靶机IP扫描 3、探测靶机主机、端口、服务版本信息 4、靶机目录扫描 二、web渗透测试 1、访问靶机IP 查看页面功能点,发现一个搜索框和登录框 2、测试一下是否存在sql注入 查看当前数…...

javaweb的新能源充电系统pf
TOC springboot339javaweb的新能源充电系统pf 第1章 绪论 1.1 课题背景 二十一世纪互联网的出现,改变了几千年以来人们的生活,不仅仅是生活物资的丰富,还有精神层次的丰富。在互联网诞生之前,地域位置往往是人们思想上不可跨域…...

如何在桌面同时展示多个窗口
一、实现2分屏显示 win箭头 二、实现3分屏显示 1. 在实现2分屏显示的基础上,再次点击箭头图标,这次选择屏幕的上方或下方。 2. 点击后,第三个窗口将会出现在你选择的区域。现在,你可以在三个窗口之间自由切换,提高工…...

The Sandbox 游戏制作教程(第 5 部分):创建基于分类的系统
欢迎回到我们的系列,我们将记录 The Sandbox Game Maker 的 “On-Equip”(装备)功能的多种用途。 如果你刚加入 The Sandbox,装备功能是 “可收集组件”(Collectable Component)中的一个多功能工具&#x…...
HTML浏览器缓存(Browser Cache)
介绍: 浏览器缓存是Web缓存中最直接、最常见的一种形式。当浏览器首次请求某个资源时,如果服务器响应中包含了缓存控制指令(如Cache-Control、Expires等),浏览器就会将这些资源存储在本地缓存中。后续请求相同资源时&a…...

短剧APP系统,推动短剧市场发展
近年来,短剧作为一直火爆的新兴行业,凭借着剧情进奏、爽、时长短等优势,深受大众欢迎,成为了大众碎片化时间的解压神器。 目前,随着短剧市场的快速发展,各个类型的短剧层出不穷,也推动了短剧AP…...
从零实现富文本编辑器#5-编辑器选区模型的状态结构表达
先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...

selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...

echarts使用graphic强行给图增加一个边框(边框根据自己的图形大小设置)- 适用于无法使用dom的样式
pdf-lib https://blog.csdn.net/Shi_haoliu/article/details/148157624?spm1001.2014.3001.5501 为了完成在pdf中导出echarts图,如果边框加在dom上面,pdf-lib导出svg的时候并不会导出边框,所以只能在echarts图上面加边框 grid的边框是在图里…...

VSCode 没有添加Windows右键菜单
关键字:VSCode;Windows右键菜单;注册表。 文章目录 前言一、工程环境二、配置流程1.右键文件打开2.右键文件夹打开3.右键空白处打开文件夹 三、测试总结 前言 安装 VSCode 时没有注意,实际使用的时候发现 VSCode 在 Windows 菜单栏…...
EC2安装WebRTC sdk-c环境、构建、编译
1、登录新的ec2实例,证书可以跟之前的实例用一个: ssh -v -i ~/Documents/cert/qa.pem ec2-user70.xxx.165.xxx 2、按照sdk-c demo中readme的描述开始安装环境: https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-c 2…...

【自然语言处理】大模型时代的数据标注(主动学习)
文章目录 A 论文出处B 背景B.1 背景介绍B.2 问题提出B.3 创新点 C 模型结构D 实验设计E 个人总结 A 论文出处 论文题目:FreeAL: Towards Human-Free Active Learning in the Era of Large Language Models发表情况:2023-EMNLP作者单位:浙江大…...
C++ 使用 ffmpeg 解码 rtsp 流并获取每帧的YUV数据
一、简介 FFmpeg 是一个开源的多媒体处理框架,非常适用于处理音视频的录制、转换、流化和播放。 二、代码 示例代码使用工作线程读取rtsp视频流,自动重连,支持手动退出,解码并将二进制文件保存下来。 注意: 代…...