【1】类型进行参数化,模板的意义是什么?
- 可以定义类型变量,来接受用户传入的类型
template<> : 定义模板参数列表
typename T,typename E, typenameR :类型变量,可以定义很多,用逗号分隔
eg: template<typename T>
类模板 =》 实例化 =》模板类
【2】模板的代码,在没有实例化之前,是不编译的
【3】类模板的选择性实例化 <最后附上代码>
- 类模板实现链表
- 类模板实现循环队列
- 类模板实现优先级队列(大根堆)
***** 指针,引用,const *****
C语言中:
- const是个常变量
c++中:
- const可以作为常量 ( 所有使用常量名字的地方,都被常量的值替换了 ) 直接初始化, 如:const int a = 10; 此处a是常量
- 也可以作为常变量 (看初始值是不是一个立即数 10 20 30) 赋的值是一个变量,如:int a = 10; const int b = a; 此处b为常变量
const和一级指针的结合 const修饰的 常量或常变量 都是保证不能被直接或间接的修改
int a =10 ; int *p =&a ;
const int b = 20 ;//此处b是个常量 const int * p2 = &b;
const和引用的结合
【1】
int a ; int &b =a; // 一般情况下,不允许给&b直接赋一个常量 例如 int & b =10; 这是不被允许的。会报错
const int &b = 10; //常引用。前面加const,才可以给他赋常量 可以用下面的方法理解,按理说&b是会保存10 的地址 并且也是可以修改值的。但是10是一个常量,肯定不会让你修改,所以必须加const
【2】
const int a = 10; const int &b = a; // 此处必须加const , 因为给&b 赋的值为a,a属于常变量,所以不允许b访问并修改他 的值,除非&b 加个const 限定。保证不会修改
int c =20; const int d = c; const int &e = d;
只要是定义指针或者引用等可以访问常量或常变量地址的,给其赋常量或常变量时。都必须加const ,从而保证不会修改
用临时对象初始化同类型新对象的时候,临时对象就不产生了,用构造临时对象的方式,直接构造新对象 --------------> Test t1= Test(10,10)
t1= 10; 要生成临时对象 int=>Test
其他类型 => 类类型 Test(int)
类类型 => 其他类型 对其他类型提供类型重载函数
Test t1(10, 10);
//地址变化00DB032C Test(int, int)
int main()
{
Test t2(20, 20);//构造t2 ma=20;mb=20;
//地址变化 0046FC94 Test(int, int)
Test t3 = t2; //拷贝构造
//地址变化 0046FC94=>0046FC84
static Test t4 = Test(30, 30); //构造t4 ma=30;mb=30;
//地址变化 00DB0334 Test(int, int)
t2 = Test(40, 40);//先构造test临时对象,ma=mb=40;再调用赋值函数,再析构test
//地址变化0046FAE4 Test(int, int) 0046FAE4=>0046FC9 operator= 0046FAE4 ~Test()
t2 = (Test)(50, 50);//构造test临时对象,ma=50,mb=5;再调用赋值函数,再析构test
//地址变化0046FAF4 Test(int, int) 0046FAF4=>0046FC94 operator= 0046FAF4 ~Test()
t2 = 60;//调用构造函数,构造临时对象,ma=60,mb=5。然后赋值,然后析构临时
//地址变化0046FB04 Test(int, int) 0046FB04=>0046FC94 operator= 0046FB04 ~Test()
Test *p1 = new Test(70, 70);//构造 堆上 ma=mb=70
//地址变化0089DFD8 Test(int, int)
Test *p2 = new Test[2]; //2次构造 堆上 但是ma=mb=5;
//地址变化0089C64C Test(int, int) 0089C654 Test(int, int)
Test *p3 = &Test(80, 80);//构造 析构
//地址变化0046FB44 Test(int, int) 0046FB44 ~Test()
Test &p4 = Test(90, 90);//构造
//地址变化0046FC44 Test(int, int)
delete p1; //地址变化0089DFD8 ~Test()
delete[]p2; //地址变化0089C654 ~Test() 0089C64C ~Test()
} //地址变化0046FC44~Test() 析构&p4指向的临时对象
Test t5(100, 100);
//地址变化00DB0320 Test(int, int)
//构造t1 t5 t2 t3 t4
//析构t3 t2 t4 t5 t1
/*
t1:Test(int, int) t5:Test(int, int)
t2:Test(int, int) t3:Test(const Test&) t4:Test(int, int)
临时:Test(int, int) operator= ~Test()
临时:Test(int, int) operator= ~Test()
临时:Test(int, int) operator= ~Test()
临时:Test(int, int) ~Test() p1 Test(int, int)
临时:Test(int, int) Test(int, int) p2 Test(int, int)~Test()~Test()
临时:Test(int, int) p3 Test(int, int)
临时:Test(int, int) ~Test()
p1 ~Test() p2 ~Test()
p3 ~Test() 临时~Test()
t3~Test() t2~Test() t4~Test() t5~Test() t1~Test()
*/
//栈
template<typename T=int>
class CStack
{
public:
CStack(int size = 10);
~CStack();
void push(const T &val);
void pop();
T top();
bool full() { return _top == _size; }
bool empty() { return _top == 0; }
private:
T *_pStack;
int _top;
int _size;
};
template<typename T = int>
CStack<T>::CStack(int size)
:_size(size), _top(0)
{
_pStack = new T[_size];
}
template<typename T = int>
CStack<T>::~CStack()
{
delete[]_pStack;
_pStack = NULL;
}
template<typename T = int>
void CStack<T>::push(const T & val)
{
if (full())
{
T *ptmp = new T[_size * 2];
for (int i = 0; i < _size;i++)
{
ptmp[i] = _pStack[i]; // 高级代码 =》 汇编码
}
_size *= 2;
delete _pStack;
_pStack = ptmp;
}
_pStack[_top++] = val;
}
template<typename T>
void CStack<T>::pop()
{
if (empty())
{
return;
}
_top--;
}
template<typename T>
T CStack<T>::top()
{
return _pStack[_top - 1];
}
//大根堆实现优先级队列
template<typename T>
class PriorityQueue
{
public:
// PriorityQueue p1; PriorityQueue p2(20)
PriorityQueue(int size = 15);
~PriorityQueue();
void push(const T &val); // 入优先级队列
void pop(); // 出优先级队列
T top(); // 获取堆顶元素
int Size(); // 返回优先级队列元素的个数
bool full(); // 判断满
bool empty(); // 判空
private:
T *_pQue;
int _cur;
int _size; // 记录队列增长的长度值
void siftUp(int i, const T &val) // 堆的上浮函数
{
while (i > 0) // i表示当前节点
{
int p = (i - 1) / 2; // p表示i节点的父节点
if (val > _pQue[p]){
_pQue[i] = _pQue[p];
i = p;
}
else{
break;
}
}
_pQue[i] = val;
}
void siftDown(int i, const T &val)
{
// i表示父节点 k表示左孩子
for (int k = 2 * i + 1; k < _cur; k = 2 * k + 1)
{
//右孩子值如果大于左孩子,则调整k为右孩子的下标
if (k + 1 < _cur && _pQue[k] < _pQue[k + 1]){
k++;
}
//k一定表示的是值最大的孩子的下标
if (val < _pQue[k]){
_pQue[i] = _pQue[k];
i = k;
}
else{
break;
}
}
_pQue[i] = val;
}
};
template<typename T>
PriorityQueue<T>::PriorityQueue(int size)
:_front(0), _rear(0), _size(size)
{
_pQue = new T[_size];
}
template<typename T>
PriorityQueue<T>::~PriorityQueue()
{
delete _pQue;
_pQue = NULL;
}
template<typename T>
void PriorityQueue<T>::push(const T &val)
{
if (full()) //如果满了,2倍内存扩容
{
T *ptmp = new T[_size * 2];
for (int i = _front; i != _rear; i = (i + 1) % _size)
{
for (int j = 0; j < _size; j++)
{
ptmp[j] = _pQue[i];
}
}
_size *= 2;
delete _pQue;
_pQue = ptmp;
_front = 0;
_rear = _size;
}
//从刚入队那个数开始和其父结点比较,如果大于父结点的值,则交换
_pQue[_rear] = val;
for (int i = (_rear-1) / 2; i >=0; i--)
{
Adjust(_pQue, i, _rear);
}
_rear = (_rear + 1) % _size;
}
template<typename T>
void PriorityQueue<T>::pop()
{
if (empty())
{
return;
}
_front = (_front + 1) % _size;
}
template<typename T>
T PriorityQueue<T>::top()
{
return _pQue[_front];
}
template<typename T>
bool PriorityQueue<T>::full()
{
return (_rear + 1) % _size == _front;
}
template<typename T>
bool PriorityQueue<T>::empty()
{
return _rear == _front;
}
template<typename T>
int PriorityQueue<T>::Size()
{
return _rear - _front;
}
//单链表
template<typename T = int>
class Link
{
public:
Link();
~Link();
void insert(const T &val);
void remove(const T &val);
void show();
private:
// 嵌套类
struct Node
{
Node(T val = T()) :_data(val), _next(NULL){}
T _data;
Node *_next;
};
// 指向头结点的指针
Node *_head;
};
template<typename T = int>
Link<T>::Link()
{
_head=new Node();
}
template<typename T = int>
Link<T>::~Link()
{
Node *pdel = NULL;
while (_head->_next != NULL)
{
pdel=_head->_next;
_head->_next=pdel->_next;
delete pdel;
pdel=NULL;
_head->_next=NULL;
}
delete _head;
}
template<typename T = int>
void Link<T>::insert(const T &val)
{
Node *pcur = _head;
while (pcur->_next != NULL)
{
pcur = pcur->_next;
}
pcur->_next = new Node(val);
}
template<typename T = int>
void Link<T>::remove(const T &val)
{
Node*p = _head; Node*pcur=_head->_next;
while (pcur != NULL)
{
if (pcur->_data == val)
{
p->_next=pcur->_next;
delete pcur;
pcur=p->_next;
}
else
{
p = pcur;
pcur = pcur->_next;
}
}
}
template<typename T = int>
void Link<T>::show()
{
Node*p = _head->_next;
while (p != NULL)
{
cout << p->_data << endl;
p = p->_next;
}
}