首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【C++】模版初阶以及STL的简介

【C++】模版初阶以及STL的简介

作者头像
s-little-monster
发布于 2024-07-20 08:50:22
发布于 2024-07-20 08:50:22
21800
代码可运行
举报
运行总次数:0
代码可运行

一、模版初阶

1、泛型编程

我们在先前的博文中提到过函数重载交换函数swap,但是使用函数重载有几个不好的地方: 1、重载的函数仅仅是类型不同,代码复用率比较低,所有的重载函数中只有数据类型不同,其他的都基本相同, 只要有新类型出现就需要用户自己增加对应的函数 2、代码可维护性低,其中某一函数出错可能会导致所有重载都出错

解决这个问题的方法就是有一个模具,只要相同的就直接套用,不同的替换就可以了

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

2、函数模版

(1)概念

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

(2)函数模版格式
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<typename T1,typename T2,...>
type name ()
{}

template就是一个函数模版关键字后跟<>,参数放里边 typename是一个类类型参数,也可以写成class,但不能写成struct,它代表name函数可以操作的数据类型。当调用name函数时,编译器会根据传递给函数的实参类型来推断T的具体类型 type name(){}就是一个函数

具体看这个例子:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<typename T>
void Swap( T& left, T& right)
{
	T temp = left;
	left = right;
	right = temp;
}
(3)函数模版的原理

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

在编译器的编译阶段,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用,将T确定为某一具体类型,然后产生一份专门处理该类型的代码

(4)函数模版的实例化

用不同类型的参数使用函数模版时,称为函数模版的实例化,分为显式实例化和隐式实例化

①显式实例化
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<typename T>
T Add(const T& left, const T& right)
{
    return left + right;
}

int main()
{
    int a = 10;
    double b = 20.0;
 
    // 显式实例化
    Add<int>(a, b);
    return 0;
}

格式:函数名+<数据类型>(参数)

②隐式实例化
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<typename 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);//意味着T实例化为int
	Add(d1, d2);//意味着T实例化为double
	return 0;
}

这是当两个参数类型相同的时候,如果两参数类型不同该语句不能通过编译,因为在编译期间,当编译器看到该实例化时,需要推演其实参类型,通过实参a1将T推演为int,通过实参d1将T推演为double类型,但模板参数列表中只有一个T,编译器无法确定此处到底该将T确定为int 或者 double类型而报错,所以我们要进行手动强制类型转换

注意:在模板中,编译器一般不会进行类型转换操作

(5)模版参数的匹配原则

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int Add(int left, int right)
{
	return left + right;
}

template<typename T>
T Add(const T& left, const T& right)
{
	return left + right;
}

int main()
{
	cout << Add(1, 2) << endl;//直接与非模版函数相匹配,编译器不需要进行特化
	cout << Add<int>(1, 2) << endl;//调用编译器特化的Add版本
	return 0;
}

调试结果:

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

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int main()
{
	Add(1, 2);//非模版更匹配,会直接选择非模版函数,不必再特化
	Add(1, 2.0);//模版生成的函数比非模版函数更加匹配,这样就会选择模版
	return 0;
}

③普通函数可以进行自动类型转换,模版函数不允许自动类型转换

3、类模版

(1)类模板的定义格式
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<class T1, class T2, ..., class Tn>
class name
{
 // 类内成员定义
}; 

name是类模板名

接下来我们写一个动态顺序表的模版

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<class T>
class Vector//Vector是类模版名,不是类
{
public:
	Vector(size_t capacity = 10)
		: _pData(new T[capacity])
		, _size(0)
		, _capacity(capacity)
	{}
//模版外定义函数
	~Vector();
	void PushBack(const T& data);
//模版内定义函数
	void PopBack()
	{
		_size--;
	}
	size_t Size()
	{
		return _size;
	}

private:
	T* _pData;
	size_t _size;
	size_t _capacity;
};
// 类模板中函数放在类外进行定义时,需要加模板参数列表
template <class T>
Vector<T>::~Vector()
{
	if (_pData)
		delete[] _pData;
	_size = _capacity = 0;
}
//每次函数定义都要加模版参数列表
template <class T>
void Vector<T>::PushBack(const T& data)
{
	if (_size == _capacity)
	{
		size_t newcapacity = _capacity * 2;
		T* ptr = new T[newcapacity];
		for (int i = 0; i < _size; i++)
		{
			ptr[i] = _pData[i];
		}
		delete[] _pData;//用delete[]回收new[]申请的空间
		_pData = ptr;
		_capacity = newcapacity;
	}
	_pData[_size] = data;
	_size++;
}
(2)类模板的实例化以及类函数的使用

类模板实例化需要在类模板名字后加<>,然后将实例化的类型放在里边,类模板不是类,实例化后才为类

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
int main()
{
	Vector<int> s1;
	s1.PushBack(1);
	s1.PushBack(2);
	s1.PushBack(3);
	s1.PushBack(4);
	s1.PopBack();
	cout << s1.Size() << endl;
	Vector<double> s2;
	return 0;
}

调试结果:

二、STL简介

STL是标准库的组成部分,是一个可复用的组件库和包罗数据结构与算法的软件框架

STL有四个版本,分别是惠普版本(也叫原始版本)、P.J.版本(VC)、RW版本、SGI版本(Linux

STL由容器、算法、仿函数、空间配置器、迭代器、配接器六大组件构成

STL的产生是C++的一次巨变,它使得很多底层的数据结构及算法不用再让程序员来实现,大大提高了学习和工作的效率和开发产品的进度

当然,STL也有更新慢、不支持线程安全、内部复杂、代码膨胀等问题

今日分享到此结束~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-07-18,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
C++:模版初阶 | STL简介
使用函数重载虽然可以实现,但是有一下几个不好的地方: 1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数 2. 代码的可维护性比较低,一个出错可能所有的重载均出错
小陈在拼命
2024/03/01
2150
C++:模版初阶 | STL简介
【C++】第七节—模版初阶+STL简介
那能否 告诉编译器一个模子,让编译器根据不同的类型利用该模子来生成代码呢?
云边有个稻草人
2025/04/03
890
【C++】第七节—模版初阶+STL简介
C++第八弹 -- 模板与STL简介
网上有句话说:“不懂STL,不要说你会C++”。STL是C++中的优秀作品,有了它的陪伴,许多底层的数据结构 以及算法都不需要自己重新造轮子,站在前人的肩膀上,健步如飞的快速开发。
用户11317877
2024/10/16
1190
C++第八弹 -- 模板与STL简介
【C++】模版+STL简介
如果有一个模具,通过给这个模具中填充不同材料(类型),来获得不同 材料的铸件(生成具体类型的代码),那我们将会方便很多。 泛型编程:允许函数和数据结构使用任何数据类型,而不需要为每种数据类型编写重复的代码。模板是泛型编程的基础。 模板运行时不检查数据类型,也不保证类型安全,相当于类型的宏替换。
_小羊_
2024/10/16
1210
【C++】模版+STL简介
【C++学习】模板初阶&&STL简介
使用函数重载虽然可以实现,但是有一下几个不好的地方: 💞 1、重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数。 💞 2、代码的可维护性比较低,一个出错可能所有的重载均出错。
IsLand1314
2024/10/15
1770
【C++学习】模板初阶&&STL简介
C++初阶-模板初阶
C++模板初阶 零、前言 一、泛型编程 二、函数模板 1、函数模板定义及使用 2、函数模板原理 3、函数模板实例化 4、函数模板匹配原则 三、类模板 1、类模板定义及使用 2、类模板实例化 零、前言 本章主要讲解C++的模板相关的初阶知识 一、泛型编程 用函数重载来实现交换变量函数: void Swap(int& left, int& right) { int temp = left; left = right; right = temp; } void Swap(double& left, d
用户9645905
2022/11/30
4750
C++初阶-模板初阶
C++模板(初阶)
如果我们定义了这个函数,其参数是int&类型的,也就是只能将整型的数据进行交换,那么如果我一个项目里面,不仅要进行整型的数据交换,还要浮点,自定义类型等等,那岂不是要使用很多个函数,而且函数的内容几乎一样。
二肥是只大懒蓝猫
2023/03/30
4240
C++模板(初阶)
【c++】初阶模版与STL简单介绍
在这里,typename T 定义了一个类型参数,它在函数模板被实例化时将被具体的类型替换。例如,如果你用 int 类型实例化该模板,编译器将生成一个接受 int 参数并返回 int 类型值的函数,T代表类型
用户11029103
2024/04/10
1790
【c++】初阶模版与STL简单介绍
【C++】模板初阶
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
六点半就起.
2024/10/16
1310
【C++】模板初阶
函数模版和类模版
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定 类型版本
ljw695
2024/10/18
5880
函数模版和类模版
C++底层学习预备:模板初阶
定义一个Shape基类,包含计算面积的纯虚函数,再派生出Circle和Rectangle等类,重写计算面积的函数,体现了面向对象的继承和多态特性
DARLING Zero two
2025/02/04
1010
C++底层学习预备:模板初阶
【C++】模板初阶:泛型编程的起点
泛型编程是一种编程范式,它允许在编写代码时使用一种通用的数据类型或算法,以便在不同的数据类型上进行操作,而不需要为每种数据类型编写专门的代码。泛型编程的目标是提高代码的重用性和可扩展性。
大耳朵土土垚
2024/05/06
2270
【C++】模板初阶:泛型编程的起点
初识模板及其STL
如果在C++中,存在一个摸具,通过给这个摸具中填充不同材料(类型),赖获得不同材料的锻件(即生成具体类型的代码),那么就会节省许多头发。对此C++提出模板的概念,对于模板分为函数模板以及类模板。
是店小二呀
2024/08/13
1540
初识模板及其STL
[C++]模版初阶
当我们想用一个函数完成多个类型参数的操作时,发现每次都要重新再写一个函数再使用,对于重载的函数虽然可以使用,但是每次用新的类型都需要再去重载一次函数**。** 例如实现交换的函数:
DevKevin
2024/05/24
4650
[C++]模版初阶
模板初阶介绍
1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数
用户11039545
2024/08/17
1120
模板初阶介绍
【C++】初识模板
如果在C++中,也能够存在这样一个模具,通过给这个模具中填充不同材料(类型),来获得不同材料的铸件(即生成具体类型的代码),那将会节省许多头发。巧的是前人早已将树栽好,我们只需在此乘凉。
P_M_P
2024/03/11
1380
【C++】初识模板
【C++】模板初阶
以实现交换函数为例,在C语言中即使是近乎完全一致的的功能,通过代码实现,只要参数不同,我们就需要写对应类型的不同函数名的函数,在之前的学习中,我们已经学习了函数重载,我们不再需要起不同的函数名,比起C语言方便不少,但是不容忽视的是函数重载仍然有不好的地方。
ZLRRLZ
2024/12/13
1650
【C++】模板初阶
C++中的标准化工厂—— 模板
        众所周知,C++是基于C语言的编写,所以它也继承了众多C的特性(当然也包括部分缺点),且基于它们进行改良和优化,这篇文章要讲的是模板,这算的上是C++基于C的一个“懒人利器”
比特大冒险
2023/04/16
8590
C++中的标准化工厂—— 模板
【C++模版初阶】——我与C++的不解之缘(七)
        在之前,我们想要实现一个交换两个值的函数,我们要实现好多个(int类型、double类型、char类型以及自定义类型)对于每一个类型,我们都需要实现一个交换函数:
星辰与你
2024/10/17
1200
【C++模版初阶】——我与C++的不解之缘(七)
C++之模板(上)
本文介绍了C++模板的基础概念,简单介绍了泛型编程,模板,以及模板中的函数模板与类模板等相关概念。
摘星
2023/04/28
4680
C++之模板(上)
相关推荐
C++:模版初阶 | STL简介
更多 >
LV.0
这个人很懒,什么都没有留下~
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档