函数模版
-
函数模版不是一个真实存在的函数,而是一个对函数功能框架的描述,当它具体执行时,将根据传递的实际参数决定其功能
-
函数模版是一个通用函数,其函数类型和形参类型不具体指定,可用一个虚拟的类型来代表。
-
函数模版定义的语法
-
template <类型形式参数列表(class/typename T)> 返回类型 函数名(形式参数列表)
-
函数模版定义友模版说明和函数定义组成
-
模版说明的类属参数必须在函数定义中至少出现一次
-
函数参数表中可以使用类属类型参数,也可以使用一般类型参数
-
编写函数模版的步骤
定义一个普通的函数,数据类型采用普通的数据类型
将数据类型参数化,即将其中具体的数据类型名(如 int )全部替换成由用户自定义的抽象类型参数名(如T)
在函数头前用template关键字引出对类型参数名的声明 -
实例化函数模版时,需要以类型作为参数,,模版参数的调用有以下两种方式
显示实例化函数模版 函数名<实参类型>(实参列表) 如max(4.5,4)
隐式实例化函数模版 函数名(实参列表) 如max(4.5,4) -
函数模版重载的参数匹配规则:
寻找和使用最符合函数名及参数类型的函数,若找到则调用它
寻找一个函数模版,将其实例化,产生一个匹配的模版函数,若找到则调用它
寻找可以通过类型转换进行参数匹配的重载函数,若找到则调用它
若按以上步骤均未找到匹配的函数,则调用错误
如果调用有多于一个的匹配函数可供选择,则调用匹配出现二义性。 -
类模版定义
template <类型形式参数值> class 类模版名
{
类模版体
} -
类模版成员函数定义
template<类型形式参数>
返回类型 类模版名<类型名表>::成员函数名(形式参数表)
{
函数体
} -
使用类模板生成的类,称为模板类,语法格式:
类模版名<类型实际参数表> 对象名 -
使用类模板编写程序时,注意事项
如果在全局域中声明了与模板参数同名的变量,则该变量被隐藏掉
模板参数名不能被当做类模板定义中类成员的名称
同一个模板参数名在模板参数表中只能出现一次
在不同类模版声明中,模板参数名可以被重复使用 -
写类模版的步骤:
先写一个实际的类,由于其语义明确,含义清楚,一般编写时不会出错
将此类中准备改变的类型名改为一个由用户自行指定的虚拟类型名(如T) -
模板的特化:模板参数在某种特定类型下的具体实现。也称为模板的具体化,分为函数模板特化和类模板特化。
-
函数模板实例化优先调用特化的函数。
-
类模板支持部分特化
容器
-
容器:一种对象类型,可以包含其他对象或指向其他对象的指针
-
容器分类:顺序容器,关联容器,容器适配器
-
顺序容器:vector(向量),list(链表),deque(双端队列)。vector,deque是以数组为基础。list以双向链表为基础
-
关联容器:set,multiset,map,multimap
-
容器适配器:stack,queue,priority_queue
-
向量:一个动态的顺序容器,具有连续内存地址的数据结构,通过下表运算符[]可以直接访问向量的任何元素。更快的索引元素(向数组一样),高效的在尾部插入或删除元素。
-
使用vector时,需要包含头文件#include 引用命名空间 using namespace std
-
vector的初始化
vector<元素类型>向量对象名:创建一个没有任何元素的空向量对象
vector<元素类型>向量对象名(size):创建一个大小为size的向量对象
vector<元素类型>向量对象名(n,初始值):创建一个大小为n的向量对象,并进行初始化
vector<元素类型>向量对象名(begin,end):创建一个向量对象,并初始化该向量对象中的元素(begin,end) -
vector修改元素:
a.insert(position,数值):将数值的一个备份插入到由position指定的位置上,并返回新元素的位置
a.insert(position,n,数值):将数值的n个备份插入到由position指定的位置上
a.insert(position,begin,end):将从begin 到end-1之间的所有元素备份插入到a中由position指定的位置上
a.push_back(数值):在尾部插入数据
a.pop_back():删除最后一个元素
a.resize(num):将元素个数修改为num
a.clear():从容器中删除所有元素
a.erase(position):删除由position指定位置上的元素
a.erase(begin.end):删除从begin 到end-1之间的所有元素
a.capacity():向量对象真实大小
a.max_size():向量对象的最大容量
a.size():向量对象大小
a.empty():判断vector是否为空
sort(a.begin,a.end): 向量排序,需要包含头文件(algorithm)
b.swap(a):两个向量交换
vector类包含一个 typedef iterator ,这是一个public成员,通过iterator可以声明向量容器的迭代器。如 vector::iterator it(将it声明为向量容器的迭代器), ++it(迭代器加1,使其指向容器中的下一个元素) ,*it(返回当前迭代器位置上的元素)。迭代器就是一个指针,用来存取容器中的数据元素,因为迭代器上的操作与指针上的操作是相同的 -
二维向量:向量中的元素为向量的向量 如 vector<vector> a(3,vector(4))
-
链表类模版
-
数据由若干个结点构成,每个结点都包含一个信息块,一个前驱指针,一个后驱指针,可以向前和向后进行访问,但不能随机访问。好处是每次插入或删除就会配置或释放一个元素空间,而且对空间的运用绝对精准
-
链表:存放双向链表,可以从任意一端开始遍历。
-
头文件 #include
-
list对象初始化
list<元素类型>链表对象名:创建一个没有任何元素的空链表对象
list<元素类型>链表对象名(size):创建一个大小为size的链表对象
list<元素类型>链表对象名(n,初始值):创建一个大小为n的链表对象,并进行初始化
list<元素类型>链表对象名(链表对象名):创建一个链表对象,并初始化链表对象中的元素
list<元素类型>链表对象名(begin,end):创建一个链表对象,并初始化该链表对象中的元素(begin,end) -
list对象操作
-
push_front(数值):在list开头处插入元素
-
push_back(数值):在list末尾处插入元素
-
pop_front():在list开头删除元素
-
pop_back():在list末尾删除元素
-
list迭代器:
-
iterator begin():返回指向第一个元素的迭代器
-
iterator end():返回指向最后一个元素的迭代器
-
reverse_iterator rbegin():指向第一个元素的逆向迭代器
-
reverse_iterator rend():指向最后一个元素的逆向迭代器
-
链表容器的操作
-
empty():链表为空时返回true
-
size():链表容器中元素的个数
-
max_size():链表容器中最大能容纳的元素的个数
-
assign(first,last):给容器添加新内容
-
assign(n, val):给容器添加新内容
-
insert(position,val):插入元素
-
insert(position n,val):插入n个元素val
-
insert(posrion,first,last):插入范围内的元素
-
erase(position):删除元素
-
erase(first,last):删除first,last中的值,包含LAST
-
双端队列类模版
-
元素可以从队列的两端入队和出队,也支持通过下标操作符[]进行直接访问。
-
头文件 #include
-
deque 不提容量操作,没有capacity()和reverse()
-
deque直接提供函数完成首尾元素的插入和删除。
-
其他操作为vector相同
-
关联容器
-
其中的元素都是经过排序的,主要通过关键字的方式来提高查询效率
-
map,multimap,set,multiset
-
map:具备一对一的处理能力,元素有key和value两个分量组成的一对数值(key,value)。元素的key是唯一的,给定一个key就能唯一确定一个value.
-
头文件:#include
-
map声明及初始化:
-
map<key,value> tempmap
-
{
-
{key,value}
-
}
-
通过key为下标访问,若key不存在,则用此key为键新增加一个元素。
-
map中添加元素:insert();先用下标获取元素,再赋值
-
map遍历:使用迭代器
-
元素的查找:
由于下标获取元素缺点是,当元素不存在时会自动添加,所有提供两个查询键是否存在的方法
map.count(K):容器中k出现的次数,只能是0或1
map.find(k): 存在返回该元素的迭代器,否则,返回超出末端迭代器 -
map中删除元素
-
erase(k):删除键为k的元素,返回删除元素的个数
-
erase§:删除迭代器p指向的元素。p必须指向m容器中确实存在的元素,且不能等于m.end()。返回值为void
-
erase(b,e):删除一定范围内的元素,该范围由迭代器b和e标记。b和e必须指向容器中的元素或最后元素的下一个位置,而且b要么在e前,或与e相等。返回void
-
集合类模版
-
像链表一样顺序的存储一组值,在一个集合中,集合元素即充当存储的数据,又充当数据的关键码,若只想知道值是否存在,使用set容器最合适。
-
头文件:#include
-
基本操作与map类似
-
多重集合模版类
-
multiset:支持副本键,同一值可以出现多次
-
mulimap:支持副本键,同一值可以出现多次
-
容器适配器
-
stack:与数据结构中的栈对应,先进后出的特性。允许在顶部插入或删除元素,但不能访问中间的元素。
-
queue:对列,先进先出的特性
-
priority_queue:带优先级的队列,元素可按某种优先级进行删除
-
头文件#include
-
初始化
-
stack sk
-
stack<int,vector> stk
-
成员函数:
push:从栈顶插入元素
pop:从栈顶删除元素
empty():检查栈是否为空,并返回一个bool值
size():返回栈中元素的个数
top():获取指向栈顶元素的引用 -
队列queue
-
只允许从末尾插入元素和从开头删除元素。不允许访问中间的元素,但可以访问开头和末尾的元素
-
queue q
-
头文件#include
-
成员函数
push:从队尾插入元素,即最后位置
pop:从队首删除元素,即最开始位置
empty():检查队列是否为空,并返回一个bool值
size():返回队列中元素的个数
front():返回指向队首元素的引用
back():返回指向队尾元素的引用 -
优先级队列 priority_queue
-
与queue的不同之处:包含最大值的元素位于队首,且只能在队首执行操作
-
头文件#include
-
priority_queque的成员函数,没有front(),back()
push:在队列中插入一个元素
pop:从队首删除元素,即最大的元素
empty():检查队列是否为空,并返回一个bool值
size():返回队列中元素的个数
top():返回指向队首元素的引用 -
算法
-
fill(first,last,val):将指定的值val分配给指定范围的每个元素
-
头文件 #include
-
copy(first,last,start):将一个范围复制到另一个范围。fist,last 被复制元素的区间。start,复制到的目标区间的起始位置,返回值,已被复制元素区间的最后一个位置的迭代器。
-
merge(first1,last1,fisrt2,last2,resultstart):将两个有序的序列合并为一个有序的序列。
-remove(first,last):将指定范围内的指定元素移除,不是真删除,是将该元素用后面额元素覆盖,因此容器长度不变,而未被移除的元素将会向前复制,后面多于的元素将不会移除
-replace(first,last,old,new): 遍历范围 [first, last),并将所有等于 old 的元素替换为 new -
find(fist,last,val):在指定的范围内搜索与指定值匹配的第一个元素,若找到返回元素第一次出现的位置,否则返回序列的尾部
-
search(first1,last1,first2,last2):在fisrt1,last1 范围内查找fist2,last2范围是否存在,若存在,返回fist2在first1第一次出现的位置,否则返回first1的末尾位置
-
equal(first1,last1,first2start):判断first1,last1范围内的对象序列是否与另一个容器以fist2开始的对象序列一一对应相等。返回bool值
-
mismatch(first1,last1,first2start):它用于比较两个范围中的元素,并找到第一个不匹配的元素对。它返回两个迭代器,分别指向两个范围中第一个不匹配的元素。如果两个范围中的所有元素都匹配,那么返回的迭代器将分别指向两个范围的末尾。
-
sort(first,last):使用指定排序标准对指定范围内的元素进行排序。默认升序排序
-
reverse(first,last):对范围内的对象进行反转