C++底层学习预备:模板初阶

文章目录

  • 1.编程范式
  • 2.函数模板
    • 2.1 函数模板概念
    • 2.2 函数模板原理
    • 2.3 函数模板实例化
      • 2.3.1 隐式实例化
      • 2.3.2 显式实例化
    • 2.4 模板参数的匹配原则
  • 3.类模板
  • 希望读者们多多三连支持
  • 小编会继续更新
  • 你们的鼓励就是我前进的动力!

进入STL库学习之前我们要先了解有关模板的学习,以便在学习完STL库使用之后,能更深入的了解其底层工作原理

1.编程范式

编程范式指的是我们使用编程的基本风格和方法
常见的方式有以下几种:

面向对象编程(OOP)

将数据和操作数据的方法封装在类中,通过类的实例(对象)来进行交互,强调数据的封装、继承和多态性

定义一个Shape基类,包含计算面积的纯虚函数,再派生出CircleRectangle等类,重写计算面积的函数,体现了面向对象的继承多态特性

函数式编程

将计算视为函数的组合和应用,强调不可变数据和纯函数,避免副作用,注重函数的输入输出关系

使用std::functionlambda表达式可以方便地进行函数式编程,如用lambda表达式定义一个简单的加法函数,不修改外部状态,只返回计算结果

过程式编程

以过程(函数)为中心,将程序分解为一系列的步骤和函数调用,数据和操作数据的函数相对独立

传统的C语言风格的编程方式,如编写一个计算阶乘的函数,通过循环递归来实现计算过程,就是典型的过程式编程

泛型编程

定义函数、类或其他程序结构时,不指定具体的数据类型,而是使用类型参数来代表未知的数据类型

algorithm头文件中的swap函数就是一种常见的泛式编程,他不指定任何类型就能实现交换,依靠的就是泛式编程,也是我们接下来要学习的模板

2.函数模板

在还不知道头文件前实现swap函数通常是这样的:

void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}
void Swap(double& left, double& right)
{double temp = left;left = right;right = temp;
}
void Swap(char& left, char& right)
{char temp = left;left = right;right = temp;
}......

为了符合各个场景下实现参数互换,要对同一个函数实现不同类型的函数重载,这种方式固然可行,但是每个类型都写一遍太过于冗余了

  1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数
  2. 代码的可维护性比较低,一个出错可能所有的重载均出错

2.1 函数模板概念

我们知道文字的印刷是依靠活字印刷术的模板实现的,那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?

这里用到的模板就是函数模板其语法形式为:

template<typename T1, typename T2,......,typename Tn>

template就是模板的意思,是用来定义模板参数关键字,也可以使用class,切记:不能使用struct代替class,因为structclass的默认权限不同,会导致一些混淆和潜在的问题

2.2 函数模板原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器

举个例子:

template<typename T>
void Swap(T& a, T& b)
{T temp = a;a = b;b = temp;
}

实现一个Swap交换函数

在这里插入图片描述
对两个不同类型的函数进行同一个函数的调用,调试模式下转到反汇编可以发现,两个函数式模板示例化后被调用的

这直接说明了调用的不是同一个函数

在这里插入图片描述
在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。

比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,这个类型无论是内置类型还是自定义类型都可以

2.3 函数模板实例化

用不同类型的参数使用函数模板时,称为函数模板的实例化

2.3.1 隐式实例化

让编译器根据实参推演模板参数的实际类型叫作隐式实例化

template<class T>
T Add(const T& left, const T& right)
{return left + right;
}int main()
{int a1 = 10, a2 = 20;double d1 = 10.0, d2 = 20.0;Add(a1, a2);Add(d1, d2);return 0;
}

正常情况下的调用就是隐式实例化

🔥值得注意的是: Add函数前加const是因为这里如果像下面例子一样进行强制转化会生成临时变量,具有常性

该知识点在前面有提到过:

传送门:C++命运石之门代码抉择:C++入门(中)

2.3.2 显式实例化

在函数名后的<>中指定模板参数的实际类型叫作显式实例化

Add(a1, d1);

还是上面的例子,如果既调用int,又调用double,到底是用哪种类型编译器无法决定,就需要显式实例化

🚩用户自己来强制转化

Add(a1, (int)d1);

🚩使用显式实例化

Add<int>(a1, d1);

指定T的类型为int

这通常不是显式实例化的常用场景,举个例子:

template<class T>
T* Alloc(int n)
{return new T[n];
}int main()
{Alloc<int>(5);return 0;
}

如果写成Alloc(5),编译器不知道你要分配的是int数组double数组还是其他类型的数组,所以无法自动推导T的类型,这时候就需要显式指定模板参数,像Alloc<int>(5) 这样明确告诉编译器T是int类型

2.4 模板参数的匹配原则

🚩一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数

// 专门处理int的加法函数
int Add(int left, int right)
{return left + right;
}// 通用加法函数
template<class T>
T Add(T left, T right)
{return left + right;
}void Test()
{Add(1, 2); // 与非模板函数匹配,编译器不需要特化Add<int>(1, 2); // 调用编译器特化的Add版本
}

🚩对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板

// 专门处理int的加法函数
int Add(int left, int right)
{return left + right;
}// 通用加法函数
template<class T1, class T2>
T1 Add(T1 left, T2 right)
{return left + right;
}void Test()
{Add(1, 2); // 与非函数模板类型完全匹配,不需要函数模板实例化Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函}

🚩模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

这里的自动转化就是上面的实例化中的转化,也要和auto自动推导区分开,不是同一个东西

3.类模板

类模板其实和函数模板是类似的

其语法形式为:

template<class T1, class T2, ..., class Tn>

因为类不像函数那样语法上支持自动类型转化,所以类模板调用必须显式实例化

// 动态顺序表
// 注意:Vector不是具体的类,是编译器根据被实例化的类型生成具体类的模具
template<class T>
class Vector
{
public:Vector(size_t capacity = 10): _pData(new T[capacity]), _size(0), _capacity(capacity){}// 使用析构函数演示:在类中声明,在类外定义。~Vector();void PushBack(const T& data)void PopBack()// ...size_t Size() { return _size; }T& operator[](size_t pos){assert(pos < _size);return _pData[pos];}private:T* _pData;size_t _size;size_t _capacity;
};
// 注意:类模板中函数放在类外进行定义时,需要加模板参数列表
template <class T>
Vector<T>::~Vector()
{if (_pData)delete[] _pData;_size = _capacity = 0;
}int main()
{// Vector类名,Vector<int>才是类型Vector<int> s1;Vector<double> s2;return 0;
}

我们在写模板类时尽量不要声明定义分离,原因有些复杂放在模板进阶的时候讲,如果一定分离的话要注意:

  1. 对于普通类,类名和类型一样
  2. 对于模板类Vector类名Vector<int>才是类型

希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/11830.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Baklib如何在知识管理领域成为领军者与六款产品的综合评析

内容概要 在知识管理领域&#xff0c;Baklib凭借其卓越的技术和创新的产品线&#xff0c;已经确立了行业的领导地位。作为一个全面的知识管理平台&#xff0c;Baklib为企业提供了高效、便捷的知识存储和管理方案&#xff0c;帮助组织有效整合内外部知识资源。其主要特点包括强…

Baklib阐明企业内容管理与内容中台的本质差异

内容概要 在快速发展的数字时代&#xff0c;企业对信息的管理愈加重视。内容管理在企业日常运营中扮演了重要角色&#xff0c;而随着技术的不断进步&#xff0c;内容中台的概念逐渐走入视野。了解这两者的不同&#xff0c;不仅有助于企业更有效地管理内容&#xff0c;还能提升…

Java 大视界 -- Java 大数据在智能电网中的应用与发展趋势(71)

&#x1f496;亲爱的朋友们&#xff0c;热烈欢迎来到 青云交的博客&#xff01;能与诸位在此相逢&#xff0c;我倍感荣幸。在这飞速更迭的时代&#xff0c;我们都渴望一方心灵净土&#xff0c;而 我的博客 正是这样温暖的所在。这里为你呈上趣味与实用兼具的知识&#xff0c;也…

deepseek 本地化部署和小模型微调

安装ollama 因为本人gpu卡的机器系统是centos 7, 直接使用ollama会报 所以ollama使用镜像方式进行部署&#xff0c; 拉取镜像ollama/ollama 启动命令 docker run -d --privileged -v ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama 查看ollama 是否启动…

【腾讯前端面试】纯css画图形

之前参加腾讯面试&#xff0c;第一轮是笔试&#xff0c;面试官发的试卷里有一题手写css画一个扇形、一个平行四边形……笔试时间还是比较充裕的&#xff0c;但是我对这题完全没有思路&#x1f62d;于是就空着了&#xff0c;最后也没过。 今天偶然翻到廖雪峰大佬的博客里提到了关…

物联网 STM32【源代码形式-ESP8266透传】连接OneNet IOT从云产品开发到底层MQTT实现,APP控制 【保姆级零基础搭建】

一、MQTT介绍 MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传输协议&#xff09;是一种基于发布/订阅模式的轻量级通讯协议&#xff0c;构建于TCP/IP协议之上。它最初由IBM在1999年发布&#xff0c;主要用于在硬件性能受限和网络状况不佳的情…

探秘Linux IO虚拟化:virtio的奇幻之旅

在当今数字化时代&#xff0c;虚拟化技术早已成为推动计算机领域发展的重要力量。想象一下&#xff0c;一台物理主机上能同时运行多个相互隔离的虚拟机&#xff0c;每个虚拟机都仿佛拥有自己独立的硬件资源&#xff0c;这一切是如何实现的呢&#xff1f;今天&#xff0c;就让我…

MATLAB实现单层竞争神经网络数据分类

一.单层竞争神经网络介绍 单层竞争神经网络&#xff08;Single-Layer Competitive Neural Network&#xff09;是一种基于竞争学习的神经网络模型&#xff0c;主要用于数据分类和模式识别。其核心思想是通过神经元之间的竞争机制&#xff0c;使得网络能够自动学习输入数据的特…

网络协议基础

文章目录 前言一、网络协议分层1.应用层2.传输层3.网络层4.数据链路层5.物理层 二、图解IP1.IP基本认识&#xff08;1&#xff09;IP的作用&#xff08;2&#xff09;IP与MAC的关系 2.IP地址的基础知识&#xff08;1&#xff09;IP地址的定义&#xff08;2&#xff09;IP地址的…

(CICD)自动化构建打包、部署(Jenkins + maven+ gitlab+tomcat)

一、平滑发布与灰度发布 **什么叫平滑&#xff1a;**在发布的过程中不影响用户的使用&#xff0c;系统不会因发布而暂停对外服务&#xff0c;不会造成用户短暂性无法访问&#xff1b; **什么叫灰度&#xff1a;**发布后让部分用户使用新版本&#xff0c;其它用户使用旧版本&am…

【C语言】自定义类型讲解

文章目录 一、前言二、结构体2.1 概念2.2 定义2.2.1 通常情况下的定义2.2.2 匿名结构体 2.3 结构体的自引用和嵌套2.4 结构体变量的定义与初始化2.5 结构体的内存对齐2.6 结构体传参2.7 结构体实现位段 三、枚举3.1 概念3.2 定义3.3 枚举的优点3.3.1 提高代码的可读性3.3.2 防止…

deep generative model stanford lecture note3 --- latent variable

1 Introduction 自回归模型随着gpt的出现取得很大的成功&#xff0c;还是有很多工程上的问题并不是很适合使用自回归模型&#xff1a; 1&#xff09;自回归需要的算力太大&#xff0c;满足不了实时性要求&#xff1a;例如在自动驾驶的轨迹预测任务中&#xff0c;如果要用纯自回…

变形金刚多元宇宙

涉及的公司&#xff1a; 日本Takara公司 Diaclone可变形机器人玩具 Microman可变形机器人玩具 孩之宝 孩之宝与Takara签订协议后&#xff0c;孩之宝开始使用Takara的专利进行研发。 漫威 为了推广玩具&#xff0c;1984年5月&#xff0c;孩之宝玩具与漫威《变形金刚》漫画试探…

Day33【AI思考】-分层递进式结构 对数学数系的 终极系统分类

文章目录 **分层递进式结构** 对数学数系的 **终极系统分类**总览**一、数系演化树&#xff08;纵向维度&#xff09;**数系扩展逻辑树**数系扩展逻辑** **二、代数结构对照表&#xff08;横向维度&#xff09;**数系扩展的数学意义 **三、几何对应图谱&#xff08;空间维度&am…

蓝桥杯python基础算法(2-1)——排序

目录 一、排序 二、例题 P3225——宝藏排序Ⅰ 三、各种排序比较 四、例题 P3226——宝藏排序Ⅱ 一、排序 &#xff08;一&#xff09;冒泡排序 基本思想&#xff1a;比较相邻的元素&#xff0c;如果顺序错误就把它们交换过来。 &#xff08;二&#xff09;选择排序 基本思想…

对象的实例化、内存布局与访问定位

一、创建对象的方式 二、创建对象的步骤: 一、判断对象对应的类是否加载、链接、初始化: 虚拟机遇到一条new指令&#xff0c;首先去检查这个指令的参数能否在Metaspace的常量池中定位到一个类的符号引用&#xff0c;并且检查这个符号引用代表的类是否已经被加载、解析和初始化…

OSCP - Proving Grounds - Roquefort

主要知识点 githook 注入Linux path覆盖 具体步骤 依旧是nmap扫描开始&#xff0c;3000端口不是很熟悉&#xff0c;先看一下 Nmap scan report for 192.168.54.67 Host is up (0.00083s latency). Not shown: 65530 filtered tcp ports (no-response) PORT STATE SERV…

Python + Tkinter + pyttsx3实现的桌面版英语学习工具

Python Tkinter pyttsx3实现的桌面版英语学习工具 在多行文本框输入英文句子&#xff0c;双击其中的英文单词&#xff0c;给出英文读音和中文含义和音标。 本程序查询本地词典数据。通过菜单栏"文件"->"打开词典编辑器"进入编辑界面。 词典数据存储…

实验六 项目二 简易信号发生器的设计与实现 (HEU)

声明&#xff1a;代码部分使用了AI工具 实验六 综合考核 Quartus 18.0 FPGA 5CSXFC6D6F31C6N 1. 实验项目 要求利用硬件描述语言Verilog&#xff08;或VHDL&#xff09;、图形描述方式、IP核&#xff0c;结合数字系统设计方法&#xff0c;在Quartus开发环境下&#xff…

17.3.4 颜色矩阵

版权声明&#xff1a;本文为博主原创文章&#xff0c;转载请在显著位置标明本文出处以及作者网名&#xff0c;未经作者允许不得用于商业目的。 17.3.4.1 矩阵基本概念 矩阵&#xff08;Matrix&#xff09;是一个按照长方阵列排列的复数或实数集合&#xff0c;类似于数组。 由…