【C++】模板详细讲解(含反向迭代器)
欢迎来到我的Blog,点击关注哦💕
前言:
C++的模板在是泛型编程的重要组成部分,编写在不同类型上工作的代码,而无需为每个类型编写重复的代码,这有助于减少代码冗余并提高代码的可维护性。
模板
模板的介绍
- C++模板是一种强大的编程技术,它允许程序员编写与类型无关的代码,即泛型编程。
- 模板可以用于定义泛型函数和类,这些函数和类可以在编译时根据实际使用的数据类型进行实例化。
- 模板的使用提高了代码的复用性和灵活性,减少了冗余代码的编写
模板分类
函数模板
函数模板的定义通常包含以下几个部分:
- template关键字:表示接下来的声明是一个模板。
- 模板参数列表:位于尖括号
<>中,可以包含类型参数和非类型参数。 - 函数声明和定义:与普通函数类似,但使用模板参数列表中的类型来定义函数。
#include <iostream>
//函数模板
template <typename T>
T add(T a, T b) {return a + b;
}int main() {int x = 10, y = 20;double d1 = 1.5, d2 = 2.5;std::cout << "Adding two integers: " << add(x, y) << std::endl;std::cout << "Adding two doubles: " << add(d1, d2) << std::endl;return 0;
}
类模板
类模板的定义与函数模板类似,但用于定义类结构。以下是一个简单的类模板示例:
#include <iostream>template <typename T>
class SimpleContainer {
private:T data;public:SimpleContainer(T value) : data(value) {}T getData() const { return data; }void setData(T value) { data = value; }
};int main() {SimpleContainer<int> intContainer(10);std::cout << "Integer data: " << intContainer.getData() << std::endl;SimpleContainer<double> doubleContainer(3.14);std::cout << "Double data: " << doubleContainer.getData() << std::endl;return 0;
}
在这个例子中,SimpleContainer是一个类模板,它可以用于任何数据类型T。当在main函数中创建SimpleContainer的实例时,编译器会根据提供的类型参数自动生成相应的类实例。
类模板的成员函数
类模板的成员函数可以是模板函数,也可以是普通函数。模板成员函数在类模板的定义中直接声明,而普通成员函数可以在类模板外定义,此时需要显式指定模板参数。
template <typename T>
class MyClass {
public:void templateFunction(T value);void normalFunction();
};template <typename T>
void MyClass<T>::templateFunction(T value) {// Template member function
}template <typename T>
void MyClass<T>::normalFunction() {// Non-template member function, defined outside the class
}
函数模板实例化
函数模板的实例化通常发生在函数被调用时。编译器会根据传递给函数模板的参数类型,自动实例化一个特定类型的函数。例如:
template <typename T>
void print(T value) {std::cout << value << std::endl;
}int main() {print(10); // 实例化为 void print(int)print(3.14); // 实例化为 void print(double)
}
在这个例子中,print函数模板被两次调用,分别传入了int和double类型的参数,因此编译器会为每种类型生成一个具体的函数实例。
类模板实例化
类模板的实例化发生在创建类模板的实例时,或者当类模板的成员函数被调用时。例如:
template <typename T>
class Box {
public:T value;Box(T v) : value(v) {}
};int main() {Box<int> intBox(10); // 实例化为 class Box<int>Box<double> dblBox(3.14); // 实例化为 class Box<double>
}
这里,Box类模板被用于创建两个不同类型的实例,Box<int>和Box<double>。
隐式实例化与显式实例化
- 隐式实例化:当模板被调用或使用时,编译器自动进行实例化。这是最常见的情况,如上述例子所示。
- 显式实例化:在某些情况下,可能需要在编译器之外显式地实例化模板。这通常用于控制模板实例的生成,避免不必要的实例化,或者在编译时提前生成一些模板实例以提高运行时性能。显式实例化的语法如下:
template class Box<int>; // 显式实例化 Box<int>
非类型模板参数
- 非类型模板参数是C++模板中的一种机制,它允许模板在编译时期使用常量值作为参数。
template<class T ,size_t N = 10>
class sulotion
{
public:sulotion(const T& x) {_a[1] = 10;}void print(){for (int i = 0; i < 10; i++){cout << _a[i]<<" ";}cout << endl;}
private:T _a[N];
};
模板的特化
C++模板特化是一种技术,允许开发者为特定类型或类型模式提供不同的模板实现,以覆盖通用模板的默认行为。
- 必须要先有一个基础的函数模板
- 关键字template后面接一对空的尖括号<>
- 函数名后跟一对尖括号,尖括号中指定需要特化的类型
- 函数形参表: 必须要和模板函数的基础参数类型完全相同,如果不同编译器可能会报一些奇怪的错误。
全特化
- 全特化是指为某个特定的模板参数提供专门的实现,通常用于处理某个特定类型的特殊情况。
- 在全特化中,模板参数列表中的所有参数都被确定化,形成一个完全具体化的模板版本。
template<class T1, class T2>
class sulotion
{
public:sulotion(const T1& x, const T2& y): _data1(x),_data2(y){}void print(){cout << _data1 << " " << _data2 << endl;}
private:T1 _data1 ;T2 _data2 ;
};
//特化
template<>
class sulotion<int,char>
{
public:sulotion(const int& x, const char& y): _data1(x), _data2(y){}void print(){cout << _data1 << " " << _data2 << endl;}
private:int _data1;char _data2;
};
偏特化
- 偏特化是指为一组模板参数提供专门的实现,而不是针对单个特定的参数。
- 偏特化允许更细粒度的控制和更广泛的特化。类模板可以进行偏特化,但函数模板不支持偏特化,因为编译器无法区分不同的偏特化版本。
- 在偏特化中,只有部分模板参数被确定化,而其他参数保持泛型。
template<class T1, class T2>
class sulotion
{
public:sulotion(const T1& x, const T2& y): _data1(x),_data2(y){}void print(){cout << _data1 << " " << _data2 << endl;}
private:T1 _data1 ;T2 _data2 ;
};
//偏特化
template<class T1>
class sulotion<T1,char>
{
public:sulotion(const T1& x, const char& y): _data1(x), _data2(y){}void print(){cout << _data1 << " " << _data2 << endl;}
private:T1 _data1;char _data2;
};
模板的分离编译
- C++模板的分离编译是指将模板的声明和定义分离开来,以适应大型项目中模块化的开发需求。
- 传统上,类模板的声明和定义通常放在同一个头文件中,但这种做法可能导致编译速度慢和编译依赖管理复杂。
- 分离编译允许开发者将模板的声明放在头文件中,而将定义放在源文件中,这样可以减少头文件的大小,加速编译过程,并减少不必要的编译依赖。
模板分离的编译容易链接错误
解决方法:
- 将声明和定义放在同一个头文件中:这是最直接的方法,可以确保模板的声明和定义在编译时可见,从而避免链接错误。
- 显示实例化:通过在源文件中显式实例化模板,告诉编译器为特定类型生成模板实例。这种方法虽然可以解决链接错误,但会降低代码的泛化能力,因为每次使用新类型时都需要更新实例化代码。
C++对模板的应用
- 容器(Containers):提供了多种数据结构的实现,如
vector、list、deque等,这些容器通过模板类来支持不同数据类型的存储和管理。 - 迭代器(Iterators):定义了一组接口,用于遍历容器中的元素。迭代器本身也是模板类,它们抽象了对容器元素的访问方式,使得算法能够独立于具体的数据结构实现。
- 算法(Algorithms):提供了一系列的函数模板,用于执行常见的数据操作,如排序、搜索、复制等。这些算法通过模板定义,可以广泛应用于不同类型的容器。
- 函数对象(Functors):也称为仿函数,是重载了
operator()的对象,可以作为算法的参数,提供自定义的操作逻辑。函数对象同样是基于模板实现的,以支持不同类型的操作。 - 适配器(Adapters):用于修改或包装现有容器或迭代器的接口,以满足特定的使用需求。适配器也是基于模板技术实现的,提供了灵活的扩展机制
C++反向迭代器
- C++的反向迭代器是对正向迭代器的再次封装。
正向迭代器
//迭代器
template<class T,class Ref,class ptr>struct _list_iterator{typedef _list_node<T> Node;typedef _list_iterator<T, Ref,ptr> self;Node* _node;_list_iterator (Node* node):_node(node){}//重载operator*Ref& operator* (){return _node->_val;}//重载operator->ptr operator->(){return _node->_val;}//重载operator++(前置)self& operator++(){_node = _node->_next;return *this;}//重载operator++(后置)self& operator++(int){self tmp(*this);_node = _node->_next;return tmp;}//重载operator--(前置)self& operator--(){_node = _node->_prev;return *this;}//重载operator--(后置)self& operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}//重载operator!=bool operator!=(const self& it)const {return _node != it._node;}//重载operator==bool operator==(const self& it)const{return _node == it._node;}};
反向迭代器
-
iterator和reverse_itrator是成为镜像对称 -
operartor*是解引用前一个数据,也就是迭代器的end -
++就是调用正向的–,反正 – 就是++
template<class iterator ,class Ref,class Ptr>struct Reverse_Iterator{typedef Reverse_Iterator<iterator, Ref, Ptr> self;iterator _it;Reverse_Iterator(iterator it):_it(it){}Ref operator* (){iterator tmp(_it);return *(--tmp);}Ptr operator->(){return &(operator* ());}self& operator++(){--_it;return *this;}self& operator--(){++_it;return *this;}bool operator==(const self& s)const{return _it == s._it;}bool operator!=(const self& s)const{return _it != s._it;}};
相关文章:
【C++】模板详细讲解(含反向迭代器)
欢迎来到我的Blog,点击关注哦💕 前言: C的模板在是泛型编程的重要组成部分,编写在不同类型上工作的代码,而无需为每个类型编写重复的代码,这有助于减少代码冗余并提高代码的可维护性。 模板 模板的介绍 …...
haproxy七层代理详解之-完整安装部署流程及负载均衡实现-及热更新方法
一.负载均衡 1.1负载均衡时什么 负载均衡:Load Balance,简称LB,是一种服务或基于硬件设备等实现的高可用反向代理技术,负载均网络流量等)分担给指定的一个或多个后端特定的服务器或设备,从而提高了衡将特定的业务(web服务、公司…...
C++11 bind
bind bind 用来将可调用对象和参数一起进行绑定。可调用对象包括普通函数、全局函 数、静态函数、类静态函数甚至是类成员函数,参数包括普通参数和类成员。绑定后的 结果,可以使用 std::function 进行保存,并延迟调用到我们需要的时候。 绑…...
LeetCode199 二叉树的右视图
前言 题目: 199. 二叉树的右视图 文档: 代码随想录——二叉树的右视图 编程语言: C 解题状态: 成功解决! 思路 二叉树层序遍历问题的变种,右视图即意味着二叉树每层的最后一个节点。 代码 /*** Definiti…...
数据赋能(172)——开发:数据挖掘——影响因素、直接作用、主要特征
影响因素 主要影响因素如下: 数据类型与属性: 数据类型和对象的不同属性会使用不同的数据类型来描述,如年龄可能是整数类型,而生日则是日期类型。数据挖掘时需要对不同的数据类型进行不同的处理,这直接影响到挖掘算法…...
Vue:Vue3-TypeScript-Pinia-Vite-pnpm / 基础项目 / 20240807
一、项目技术栈 / 依赖 序号技术栈版本解释1node20.14.02vue 3.4.31 3vite 5.3.4 4TypeScript 5.2.2 5 types/node 22.0.2 解决TypeScript项目中缺少对应模块的类型定义文件的问题6 element-plus 2.7.8 ui组建7 types/js-cookie js-cookie 3.0.6 3.0.5 8 sass 1.77.8 9 hu…...
windows Qt 录屏 录音
启动录屏录音: connect(&m_Process, &QProcess::readyReadStandardOutput, [&]() {qDebug() << "Standard output:" << QString::fromLocal8Bit(m_Process.readAllStandardOutput()); });connect(&m_Process, &QProcess…...
AAC中的ADTS格式分析
😎 作者介绍:欢迎来到我的主页👈,我是程序员行者孙,一个热爱分享技术的制能工人。计算机本硕,人工制能研究生。公众号:AI Sun(领取大厂面经等资料),欢迎加我的…...
iOS内存管理---MRC vs ARC
系列文章目录 iOS基础—Block iOS基础—Protocol iOS基础—KVC vs KVO iOS网络—AFNetworking iOS网络—NSURLSession iOS内存管理—MRC vs ARC iOS基础—Category vs Extension iOS基础—多线程:GCD、NSThread、NSOperation iOS基础—常用三方库:Mason…...
【数学分析笔记】第1章第1节:集合(2)
这节我自己补了一些内容,要不然听不太懂陈纪修老师讲的 1. 集合与映射 1.3 子集与真子集 假如有 S \textbf{S} S和 T \textbf{T} T两个集合,其中, S \textbf{S} S的所有元素都属于 T \textbf{T} T,则称 S \textbf{S} S是 T \te…...
大话设计模式:七大设计原则
目录 一、单一职责原则(Single Responsibility Principle, SRP) 二、开放封闭原则(Open-Closed Principle, OCP) 三、依赖倒置原则(Dependency Inversion Principle, DIP) 四、里氏替换原则&am…...
利用多商家AI智能名片小程序提升消费者参与度与个性化体验:重塑零售行业的忠诚策略
摘要:在数字化浪潮席卷全球的今天,零售行业正经历着前所未有的变革。消费者对于购物体验的需求日益多样化、个性化,而零售商则面临着如何将一次性购物者转化为品牌忠诚者的巨大挑战。多商家AI智能名片小程序作为一种新兴的数字营销工具&#…...
Scala 闭包
Scala 闭包 Scala 闭包是一个非常重要的概念,它允许我们创建可以在稍后某个时间点执行的功能片段。闭包是一个函数,它捕获了封闭范围内的变量,即使在函数外部,这些变量也可以在函数内部使用。这使得闭包成为处理异步操作、回调和…...
前端JS总结(中)
目录 前言 正文 对象: 分类: 自定义对象: 内置对象: 重点: 常用内置对象: 字符串对象:String 获取字符串长度: 大小写转换: 获取某个字符: 截取字…...
elasticsearch的match_phrase匹配及其可能导致的查询问题
目录 1.match_phrase使用介绍 2.规避可能产生的查询问题 解决方式 一.查询和索引分词器一致,即都使用max_word或者都使用smart 二.使用slop增加匹配的容忍度 3.参考文档 1.match_phrase使用介绍 elasticsearch的match_phrase查询是全文查询,主要用…...
C++快速理解之继承
一、继承和派生 1.是什么? C 中的继承是类与类之间的关系,与现实世界中的继承类似 例如:儿子继承父亲的财产 继承(Inheritance)可以理解为一个类从另一个类获取成员变量和成员函数的过程 例如: 类B继承…...
Node.JS - 基础(Express)
目录 A. 简介 B. 下载,安装 C. 启动服务,查看文件结构 A. 简介 Express 是一个基于 Node.js 平台的极简、灵活的 Web 应用开发框架,它提供了一系列强大的功能来构建 Web 应用程序和 API。 一、Express 的基本特点 简洁的路由系统: Express 的路由系…...
I/O复用
I/O复用使得程序能够同时监听多个文件描述符,这对提高程序的性能至关重要。 举个例子: 就好比你天天玩手机,你妈为了监控你,在你房间安装了一个监控,这个监控可以实时监控你的一举一动,并上传到你妈手机上…...
【验证可用】解决安装SQL Server数据库时,报错“启用 windows 功能 NetFx3 时出错,错误代码:-2146498298......“的问题
目录 背景一. 报错信息1.1 报错的图片信息1.2 报错的文字信息 二. 解决报错2.1 下载 NetFx3.cab 文件2.2 执行命令 三. SQL Server 修复安装 背景 一次在阿里云服务器安装 SQL Server 2012时,系统报错了,导致安装进行不下去…通过在网上查找了多种解决方…...
STM32的SDIO接口详解
目录 1. 定义与兼容性 2. SDIO时钟 3. SDIO命令与响应 4. SDIO块数据传输 5. SDIO控制器的硬件结构 6.代码实现 1.SD初始化 2.测试SD卡的读取 3.测试SD卡的写入 STM32的SDIO(Secure Digital Input/Output,安全数字输入输出)接口是一…...
谷歌浏览器插件
项目中有时候会用到插件 sync-cookie-extension1.0.0:开发环境同步测试 cookie 至 localhost,便于本地请求服务携带 cookie 参考地址:https://juejin.cn/post/7139354571712757767 里面有源码下载下来,加在到扩展即可使用FeHelp…...
基于大模型的 UI 自动化系统
基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...
【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
React19源码系列之 事件插件系统
事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
拉力测试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作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...
