当前位置:首页 » 《关注互联网》 » 正文

【C++】模版初阶+STL介绍

29 人参与  2024年09月10日 19:21  分类 : 《关注互联网》  评论

点击全文阅读


模版

一.泛型编程二.函数模版1.函数模版的概念2.函数模板的格式3.函数模版的原理4.函数模版的实例化5.模板参数的匹配原则 三.类模版1.类模板的定义格式2.类模板的实例化 四.STL简介1.什么是STL2.STL的六大组件

一.泛型编程

当我们要交换两个变量时,可以使用函数重载,如下:

void Swap(int& x, int& y){}void Swap(double& x, double& y){}void Swap(char& x, char& y){}

但是函数重载也有不好的地方:

重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数。

代码的可维护性比较低,一个出错可能所有的重载均出错。

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

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

在这里插入图片描述

二.函数模版

1.函数模版的概念

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

2.函数模板的格式

template<typename T1, typename T2,…,typename Tn>
返回值类型 函数名(参数列表){}

如下:

template<typename T>void Swap(T& x, T& y){T tmp = x;x = y;y = tmp;}

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

3.函数模版的原理

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

在这里插入图片描述
  在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码。

4.函数模版的实例化

  用不同类型的参数使用函数模板时,生成对应的函数,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化。

隐式实例化:让编译器根据实参推演模板参数的实际类型。显式实例化:在函数名后的<>中指定模板参数的实际类型。
template<class T>T Add(const T& x, const T& y){return x + y;}int main(){int a1 = 10, a2 = 20;double d1 = 1.1, d2 = 1.2;//隐式实例化cout << Add(a1, a2) << endl;cout << Add(d1, d2) << endl;//Add(a1, d2);编译器无法确定此处到底该将T确定为int 或者 double类型而报错//推导实例化cout << Add(a1, (int)d1) << endl;    //11cout << Add((double)a1, d1) << endl; //11.1//显示实例化cout << Add<int>(a1, d1) << endl;    //11cout << Add<double>(a1, d1) << endl; //11.1return 0;}

必须显示实例化的案例:

template<class T>T* func(int n){return new T[n];}int main(){//int* p = func(10);//无法为 "T" 推导模版参数,编译报错int* p = func<int>(10);//必须显示实例化return 0;}

5.模板参数的匹配原则

一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数。对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板。模板函数不允许自动类型转换(编译报错),但普通函数可以进行自动类型转换。
template<class T>//模版参数T Add(const T& x, const T& y)//函数模版{return x + y;}int Add(const int& x, const int& y){return (x + y) * 2;}int main(){int a = 10;int b = 20;double d = 1.1;cout << Add(a, b) << endl;      //调用现成的Add函数——>60cout << Add<int>(a, b) << endl; //调用模版——>30cout << Add(a, d) << endl; //调用现成的Add函数,发生隐式类型转换——>22cout << Add(a, d) << endl; //若没有现成的Add函数——>编译错误return 0;}

三.类模版

1.类模板的定义格式

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

模版参数只能给当前类模版使用,使用一次,不能多次使用,同理模版参数也不能多次给函数模版使用,比如:

template<class T>class Stack{public:Stack(int n = 4):_array(new T[n]),_size(0),_capacity(n){}~Stack(){delete[] _array;_array = nullptr;_size = _capacity = 0;}void Push(const T& x);//void Push(const T& x)//{//if (_size == _capacity)//{////C++需要手动扩容//T* tmp = new T[_capacity * 2];//memmove(tmp, _array, sizeof(T) * _size);//delete[] _array;//_array = tmp;//_capacity *= 2;//}//_array[_size++] = x;//}private:T* _array;size_t _size;size_t _capacity;};//模版不建议声明和定义分离到两个文件.h 和.cpp会出现链接错误,但是可以到分离到同一文件template<class T>//声明模版参数void Stack<T>::Push(const T& x)//指定作用域{void Push(const T& x){if (_size == _capacity){//C++需要手动扩容T* tmp = new T[_capacity * 2];memmove(tmp, _array, sizeof(T) * _size);delete[] _array;_array = tmp;_capacity *= 2;}_array[_size++] = x;}}int main(){//类模版:都是显示实例化,实例化出不同的类型Stack<int> st1;    //intst1.Push(1);st1.Push(2);st1.Push(3);Stack<double> st2; //doublest2.Push(1.1);st2.Push(2.2);st2.Push(3.3);Stack<int>* pst = new Stack<int>;delete pst;return 0;}

在这里插入图片描述

2.类模板的实例化

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

//Stack是类名,Stack<int>才是类型Stack<int> st1;    //intStack<double> st2; //double//Stack<int>与Stack<double>是不同的类型

四.STL简介

1.什么是STL

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

原始版本: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的六大组件

在这里插入图片描述

网上有句话说:“不懂STL,不要说你会C++”。STL是C++中的优秀作品,有了它的陪伴,许多底层的数据结构以及算法都不需要自己重新造轮子,站在前人的肩膀上,健步如飞的快速开发。

简单总结一下:学习STL的三个境界:能用,明理,能扩展 。


点击全文阅读


本文链接:http://zhangshiyu.com/post/157962.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1