【C++】模板初阶和STL简介
在此之前我们已经学完了C++类和对象的相关知识,那么今天我们继续进行模版和STL的学习。
目录
- 一、模板初阶
- 1、泛型编程
- a、模板的概念
- b、模板的分类
- 2、函数模板
- 2.1、函数模板的概念
- 2.2、函数模板的格式
- 2.4、函数模板的实例化
- a、隐式实例化
- b、显式实例化
- 2.5、模板参数的匹配原则
- 3、类模板
- 3.1、定义格式
- 3.2、模板实例化
- 二、初识STL
- 1、STL概念
- 2、STL六大组件
- 3、为什么要学习STL
一、模板初阶
1、泛型编程
在我们之前的C语言学习中,当我们想实现不同类型的交换函数时,需要有不同的写法。
例如:
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;
}
当我们面对int 、double、char这三种类型时,需要写三种不同的交换函数。
但是这样写未免过于麻烦,于是C++中便引入了模板这一概念,从而引入泛型编程的概念。
a、模板的概念
C++模板是C++语言中的一个强大特性,它允许程序员创建泛型代码,即能够处理多种数据类型的代码。模板在C++中分为两种主要类型:函数模板和类模板。
泛型编程就是编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。
b、模板的分类
在C++中,C++分为函数模板和类模板。
2、函数模板
2.1、函数模板的概念
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
2.2、函数模板的格式
** template<typename T1,typename T2,…,typename Tn>
返回值类型 函数名(参数列表){}**
其中typename是用来定义模板参数关键字,也可以使用class,但是不能用struct代替class。
template<typename T>
void Swap( T& left, T& right)
{
T temp = left;
left = right;
right = temp;
}
在上面的代码中,typename也可以改为class,参数类型写成T。
总之,函数模板就相当于一个模子,任意参数类型都可以使用这个模子,十分简洁。
2.4、函数模板的实例化
C++函数模板的实例化是指在编译期间,根据实际使用的数据类型,从函数模板生成具体函数的过程。这个过程使得模板能够适应不同的数据类型,从而实现代码的复用和泛化。
模板参数实例化可以分为隐式实例化和显示实例化。
a、隐式实例化
隐式实例化是在调用函数模板时自动发生的。当你编写了一个函数模板,并在代码中调用它时,如果还没有为特定的数据类型生成对应的函数,编译器会自动为你生成这个函数。这意味着你不需要显式地指定类型,编译器会在需要的时候自动完成实例化工作。
template<class T>
T Add(const T& left, const T& right)
{
return left + right;
}
int main()
{
int a1 = 20, a2 = 30;
double b1 = 20.0, b2 = 30.0;
Add(a1, a2);
Add(b1, b2);
return 0;
}
在上面的代码中,语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型,通过实参a1将T推演为int,通过实参b1将T推演为double类型,但模板参数列表中只有一个T。编译器无法确定此处到底该将T确定为int,或者 double类型而报错。
在模板中,编译器一般不会进行类型转换操作。
那怎么办呢?
此时我们有两种处理方式:
1、用户自己来强制转换,即可以写为Add(a,(int) d ,2、使用显示实例化。
那么接下来我们继续学习显式实例化。
b、显式实例化
显式实例化则是程序员明确地告诉编译器为特定类型生成函数模板的实例。这通常通过在代码中显式地指定模板参数来实现。即使在函数调用之前,你也可以说“我要为这个特定类型生成函数模板的实例”,这样编译器就会提前准备好这个实例,无论之后是否真的会调用它。==显式实例化只需在函数名后的<>中指定模板参数的实际类型。
例如:
int main(void)
{
int a = 30;
double b = 50.0;
Add<int>(a,b);//显式实例化
return 0;
}
如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。
2.5、模板参数的匹配原则
a、一个非模板函数可以和一个同名的函数同时存在,而且该函数模板还可以被实例化为这个非模板函数。
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);
}
b、对于非模板函数和同名函数模板,如果其它条件都相同,在调动时会优先调用非模板函数而不会从该模板产出一个实例。如果模板可以产生一个具有更好匹配的函数,那么将选择模板。
c、模板函数不允许自动类型转换,但普通函数可以进行自动类型转换。
3、类模板
3.1、定义格式
template<class T1, class T2, ... ,class Tn>
class 类模板名
{
//类内成员定义
}
#include<iostream>
using namespace std;
//类模板
template<typename T>
class Stack
{
public:
Stack(size_t capacity = 4)
{
_array = new T[capacity];
_capacity = capacity;
_size = 0;
}
void Push(const T& data);
private:
T* _array;
size_t _capacity;
size_t _size;
};
template<class T>
void Stack<T>::push(const T& data)
{
//扩容
_array[_size] = data;
++_szie;
}
int main()
{
Stack<int> st1;//int
Stack<double> st2;//double
return 0;
}
模板不建议声明和定义分离到两个文件.h 和 .cpp,因为会出现链接错误·
3.2、模板实例化
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。
// Stack是类名,Stack<int>才是类型
Stack<int> st1; // int
Stack<double> st2; // double
二、初识STL
1、STL概念
STL全称为Standard Template Library,是C++标准库的一部分。它的设计理念是泛型编程,通过使用模板实现一套通用的数据结构和算法,以提高程序的可重用性和扩展性。STL的核心思想是将数据结构和算法进行分离,让容器负责数据的存储和管理,算法负责对容器中的数据进行操作和处理。
2、STL六大组件
STL(标准模板库)是C++的一个重要的组成部分,它提供了一系列的容器、算法、迭代器、函数对象、适配器和分配器,这些组件可以相互组合使用,以提高程序的效率和可读性。
STL有六大组件:
容器 用于存储数据的各种数据结构,如vector、list、deque、set、map等。
算法包括各种常用的sort、search、copy、erase、find等等。
迭代器 作为泛型指针,扮演容器和算法之间的粘合剂,用来连接容器和算法。
仿函数 让一个类看起来像一个函数,可以作为算法的某种策略。
配接器 修改类的接口,使原来不相互匹配的两个类可以相互匹配,进行合作。
空间配置器 主要负责空间的配置和管理。
3、为什么要学习STL
STL 在 C++ 编程中扮演着至关重要的角色,它不仅提高了开发效率和代码质量,还保证了程序的性能和可维护性。
C++ STL(标准模板库)的重要性主要体现在以下几个方面:
高效性:STL 提供的高度优化的数据结构和算法,使得程序运行更加高效。例如,STL 的 sort 函数在大多数情况下比手写排序更快。
类型安全性:STL 的设计遵循强类型检查的原则,减少了类型错误的可能性,提高了代码的安全性。
易用性:STL 提供了丰富的容器(如 vector、list、map 等)和算法(如 find、search 等),简化了数据结构和算法的使用,使开发者可以更专注于业务逻辑。
可重用性:STL 的组件如容器、算法和迭代器都是高度可重用的,开发者可以在不同的项目中重复使用这些组件,提高了代码的复用性。
高性能:STL 的设计考虑了性能优化,例如 vector 的动态调整大小机制,deque 的双端快速插入和删除能力等,都保证了高性能的数据操作。
高移植性:由于 STL 是 C++ 标准库的一部分,它具有很好的跨平台兼容性,可以在不同的操作系统上运行。
标准化:作为 C++ 的官方标准库,STL 提供了一致的接口和规范,使得不同开发者之间的代码更加一致和可读。
本章内容到这里就结束啦!