【STL模版库】STL入门 {模版初阶:泛型编程,函数模版,类模版;STL简介:什么是STL,STL六大组件}

news2024/11/24 5:05:27

一、模版初阶

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;
right = temp;
}
void Swap(char& left, char& right)
{
char temp = left;
left = right;
right = temp;
}
......

使用函数重载虽然可以实现,但是有一下几个不好的地方:

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

那能否告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?

泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。

在这里插入图片描述


2. 函数模板

2.1 函数模板概念

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

2.1 函数模板格式

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

返回值类型 函数名(参数列表){}

typename 后跟模版类型名可以随便取,一般取大写字母或单词首字母大写,如:T, Ty, K, V等。

template<typename T> //定义模板类型(虚拟类型)
void Swap( T& left, T& right) //定义函数模版
{
	T temp = left;
	left = right;
	right = temp;
}

注意:typename是用来定义模板类型的关键字,也可以使用class(切记:不能使用struct代替class)

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

在这里插入图片描述

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。也就是说传入不同类型的参数调用的是不同的函数,函数的地址也不同。

比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。

2.4 函数模板的实例化

利用函数模版产生具体类型的函数,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。

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

    注意:定义模版类型是可以在后面加默认值。如果缺省类型没有显示的实例化就会采用默认类型。但在调用模版函数时还要加<>。

//template<class T = int> // 定义模版类型是可以在后面加默认值
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);

	//Add(a1, d1); //编译报错;原因:只有一个模版类型,推演实例化矛盾

	// 此时有两种处理方式:1. 用户自己来强制转化 2. 使用显式实例化
	Add(a, (int)d);
    return 0;
}
  1. 显式实例化:在函数名后的<>中指定模板参数的实际类型
int main(void)
{
	int a = 10;
	double b = 20.0;
	// 显式实例化
	Add<int>(a, b);
	return 0;
}

提示:如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。

下面的函数模版必须显示实例化,因为函数参数中未指定模版参数的类型。

template<class T>
T* Func(int n)
{
    T* a = new T[n];
    return a;
}

2.5 模板参数的匹配原则

  1. 一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数
// 专门处理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(1.5, 2.5); // 调用编译器特化的Add版本
	Add<int>(1, 2); // 调用编译器特化的Add版本
}

提示:调用函数时,编译器会先看有没有同类型参数的非模板函数,如果没有才会用函数模版实例化对应的函数。

  1. 对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择该模板
// 专门处理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.0, 2); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函数
}

注意:模板函数不允许自动类型转换(除非进行显示的实例化),但普通函数可以进行自动类型转换


3. 类模板

3.1 类模板的概念

看以下代码:

typedef char STDateType;

class Stack
{
private:
    STDateType *_a;
    int top;
    int capacity;    
}

int main(){
    Stack st1; //顺序表中存储char类型
    Stack st2; //顺序表中存储int类型???
}

结论:面对这种情况,C语言无法定义存储不同类型数据的栈,除非复制代码定义不同的类,那样过于麻烦,且不利于维护。

类模版:类模板代表了一个类家族,该类模板与类型无关根据指定的模版类型产生类的特定类型版本。

3.2 类模板的定义格式

template<class T1, class T2, ..., class Tn>
class 类模板名
{
	// 类内成员定义
};

举例:定义顺序表的类模版

// 动态顺序表
// 注意: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() // 注意:Vector<T>才是类型名
{
	if(_pData)
	delete[] _pData;
	_size = _capacity = 0;
}
  • 不支持分文件编写类模版的声明和成员函数的定义。

  • 一般类模版的声明和成员函数的定义都放在一个后缀为.hpp的文件中。

注意:模版在同一个文件中是可以声明和定义分离的。

3.3 类模板的实例化

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>进行显示的实例化,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。

Vector<int> s1;
Vector<double> s2;

注意:Vector是类模版名,Vector才是实例化出的类型名


二、STL简介

1. 什么是STL

STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且
是一个包罗数据结构与算法的软件框架。

提示:STL在std命名空间当中,因此使用STL要展开std命名空间using namespace std;

STL的版本

  • 原始版本
    Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意
    运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使
    用。 HP 版本–所有STL实现版本的始祖。
  • P. J. 版本
    由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,
    符号命名比较怪异。
  • RW版本
    由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般。
  • SGI版本
    由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好,
    可公开、修改甚至贩卖,从命名风格和编程风格上看,阅读性 非常高。我们后面学习STL要阅读部分源代码,
    主要参考的就是这个版本。

2. STL的六大组件

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【Python习题集5】函数的设计

函数的设计 一、实验内容二、实验总结 一、实验内容 1.编写两个函数分别按单利和复利计算利息&#xff0c;根据本金、年利率、存款年限得到本息和和利息。调用这两个函数计算1000元在银行存3年&#xff0c;在年利率是6%的情况下&#xff0c;单利和复利分别获得的本息和和利息。…

【Java虚拟机】JVM垃圾回收器详解

1.什么是垃圾收集器 垃圾回收算法是内存回收的方法论&#xff0c;垃圾收集器则是内存回收的具体实现 目前Java规范中并没有对垃圾收集器的实现有任何规范 不同的厂商、不同的版本的虚拟机提供的垃圾收集器是不同的&#xff0c;主要讨论的是HotSpot虚拟机 不存在最厉害的垃圾…

【Java】内部类Object类

目录 1.内部类 1.1实例内部类 1.2静态内部类 1.3局部内部类 1.4匿名内部类 2.Object类 2.1getClass方法 2.2equals方法 2.3hashcode方法 1.内部类 定义&#xff1a;一个类定义在另一个类或一个方法的内部&#xff0c;前者称为内部类&#xff0c;后者称为外部类。 分…

JWT渗透与防御

JWT渗透与防御 什么是JWTJWT漏洞介绍工具使用 身份认证(Authentication)又称鉴权&#xff0c;是指通过一定的手段&#xff0c;完成对用户身份的确认。认证的方式&#xff1a;sessioncookie、JWT、Token session认证的局限性 session认证机制需要配合cookie才能实现。由于cookie…

238页9万字大数据治理与服务平台建设及数据服务实施方案(word)

本资料来源公开网络&#xff0c;仅供个人学习&#xff0c;请勿商用&#xff0c;如有侵权请联系删除。 1 项目解决方案 1.1 建设类业务技术方案 1.1.1 业务需求分析 根据对招标要求的理解&#xff0c;建设业务需求主要包括如下几个方面&#xff1a; &#xff08;1&#xff…

网站遭遇XSS注入如何排查及解决

首先要明白什么是XSS注入 存储型 XSS 的攻击步骤&#xff1a; 攻击者将恶意代码提交到目标网站的数据库中。用户打开目标网站时&#xff0c;网站服务端将恶意代码从数据库取出&#xff0c;拼接在 HTML 中返回给浏览器。用户浏览器接收到响应后解析执行&#xff0c;混在其中的…

Docker部署spring boot项目

在docker部署时首先要保证一般部署能够访问。 docker命令部署spring boot项目 目前主流的java框架为spring&#xff0c;软件包为jar包&#xff0c;只需以jar为基础构建容器环境。打包为jar后只需要jvm就可以运行&#xff0c;因此需要以jdk为镜像构建容器。 基于命令构建jdk环…

MySQL面试八股文:索引篇

索引的定义 索引是数据库中用来加速数据查询的一种数据结构。它可以将数据表中的某一列或多列进行排序&#xff0c;以便快速查找数据&#xff0c;减少数据库的扫描次数&#xff0c;提高查询速度。 索引的优缺点 索引的优点是可以大幅度提高数据查询的速度&#xff0c;尤其是…

( 数组和矩阵) 565. 数组嵌套 ——【Leetcode每日一题】

❓565. 数组嵌套 难度&#xff1a;中等 索引从 0 开始长度为N的数组 A&#xff0c;包含 0 到 N - 1 的所有整数。找到最大的集合 S并返回其大小&#xff0c;其中 S[i] {A[i], A[A[i]], A[A[A[i]]], ... } 且遵守以下的规则。 假设选择索引为 i 的元素 A[i] 为 S 的第一个元…

【Java|golang】1003. 检查替换后的词是否有效

给你一个字符串 s &#xff0c;请你判断它是否 有效 。 字符串 s 有效 需要满足&#xff1a;假设开始有一个空字符串 t “” &#xff0c;你可以执行 任意次 下述操作将 t 转换为 s &#xff1a; 将字符串 “abc” 插入到 t 中的任意位置。形式上&#xff0c;t 变为 tleft “…

【软考高项笔记】第1章 信息化发展1.3 现代化创新发展

1.3 现代化创新发展 1.3.1 农业农村现代化 采棉机&#xff0c;传感器检查温度湿度 乡村振兴战略 建设基础设施 发展智慧农业 建设数据乡村1.3.2 两化融合与智能制造&#xff08;工业&#xff09; 信息化 工业化 发展战略 坚持自主可控&#xff0c;安全高效&#xff0c;推进产业…

VESC操作入门——双轮毂电机控制和CAN通信

目录 一、VESC驱动轮毂电机1.1、硬件准备1.2、硬件接线1.3、校准电机1.4、主操作界面 二、CAN通信2.1、硬件连接2.2、代码说明2.3、发送指令 三、双轮毂电机3.1、校准第二个电机参数3.2、硬件连接3.3、CAN总线发送指令 四、把VESC做为USB转CAN模块 ODrive、VESC和SimpleFOC 教程…

【星戈瑞】Sulfo-Cyanine5 mal 磺酸跟水溶性生物标记试剂

水溶性Sulfo-Cyanine5 mal是一种用于生物标记和荧光成像的荧光染料。它的化学名称是Cyanine5 maleimide&#xff0c;分子式为C29H27ClN2O4S&#xff0c;分子量为576.05。Cyanine5 mal属于Cyanine染料家族&#xff0c;具有强烈的吸收和发射光谱&#xff0c;适用于生物分子的标记…

( 数组和矩阵) 769. 最多能完成排序的块 ——【Leetcode每日一题】

❓769. 最多能完成排序的块 难度&#xff1a;中等 给定一个长度为 n 的整数数组 arr &#xff0c;它表示在 [0, n - 1] 范围内的整数的排列。 我们将 arr 分割成若干 块 (即分区)&#xff0c;并对每个块单独排序。将它们连接起来后&#xff0c;使得连接的结果和按升序排序后…

云服务器vCPU和CPU有什么区别?

云服务器的vCPU和物理服务器的CPU有什么区别&#xff1f;阿里云百科以阿里云服务器ECS为例&#xff0c; 阿里云服务器vCPU和CPU是什么意思&#xff1f;CPU和vCPU有什么区别&#xff1f;一台云服务器ECS实例的CPU选项由CPU物理核心数和每核线程数决定&#xff0c;CPU是中央处理…

推荐算法实战项目:FNN 原理以及案例实战(附完整 Python 代码)

本文要介绍的是FNN模型&#xff0c;出自于张伟楠老师于2016年发表的论文《Deep Learning over Multi-field Categorical Data》。 论文提出了两种深度学习模型&#xff0c;分别叫做FNN&#xff08;Factorisation Machine supported Neural Network&#xff09;和SNN&#xff0…

如何利用 Kotlin 特性封装 DataStore

Jetpack DataStore是一种数据存储解决方案&#xff0c;由于使用了 Kotlin 协程或者 RxJava 以异步、一致的事务方式存储数据&#xff0c;用法相较于其它存储方案 (SharedPreferences、MMKV) 会更加特别&#xff0c;所以目前网上都没有什么比较好的 DataStore 封装。 个人了解了…

(十)Shapefile文件创建——创建Shapefile和dBASE

&#xff08;十&#xff09; Shapefile文件创建——创建Shapefile和dBASE ArcCatalog 可以创建新的 Shapefile 和 dBASE表&#xff0c;并可进行属性项及索引的操作定义 Shapefile 的坐标系统。当在目录中改变 Shapefile 的结构和特性 (Properties)时必须使用 ArcMap 来更新或重…

动态规划 --- 01背包

动态规划 — 01背包 一直到现在都非常害怕动态规划&#xff0c;因为基本上自己都无法想出dp递推式&#xff0c;太难受了 T.T 今天再一次遇到了需要写01背包的情况&#xff0c;根据自己学习的一点点经历&#xff0c;再稍微总结一下01背包吧&#xff0c;虽然是个被认为dp入门的…

自学Python必须知道的优秀社区

国内学习Python网站&#xff1a; 知乎学习平台&#xff1a;Python - 基础入门 - 知学堂黑马程序员视频库&#xff1a;大数据学习路线2023版-黑马程序员大数据学习路线图菜鸟教程&#xff1a;菜鸟教程 - 学的不仅是技术&#xff0c;更是梦想&#xff01;极客学院&#xff1a;极…