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…...
51c自动驾驶~合集58
我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留,CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制(CCA-Attention),…...
《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
python执行测试用例,allure报乱码且未成功生成报告
allure执行测试用例时显示乱码:‘allure’ �����ڲ����ⲿ���Ҳ���ǿ�&am…...
Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换
目录 关键点 技术实现1 技术实现2 摘要: 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式(自动驾驶、人工驾驶、远程驾驶、主动安全),并通过实时消息推送更新车…...
Golang——6、指针和结构体
指针和结构体 1、指针1.1、指针地址和指针类型1.2、指针取值1.3、new和make 2、结构体2.1、type关键字的使用2.2、结构体的定义和初始化2.3、结构体方法和接收者2.4、给任意类型添加方法2.5、结构体的匿名字段2.6、嵌套结构体2.7、嵌套匿名结构体2.8、结构体的继承 3、结构体与…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...
自然语言处理——文本分类
文本分类 传统机器学习方法文本表示向量空间模型 特征选择文档频率互信息信息增益(IG) 分类器设计贝叶斯理论:线性判别函数 文本分类性能评估P-R曲线ROC曲线 将文本文档或句子分类为预定义的类或类别, 有单标签多类别文本分类和多…...
基于stm32F10x 系列微控制器的智能电子琴(附完整项目源码、详细接线及讲解视频)
注:文章末尾网盘链接中自取成品使用演示视频、项目源码、项目文档 所用硬件:STM32F103C8T6、无源蜂鸣器、44矩阵键盘、flash存储模块、OLED显示屏、RGB三色灯、面包板、杜邦线、usb转ttl串口 stm32f103c8t6 面包板 …...
