先给出一段简单的代码
#include <iostream>
using namespace std;//为 using 指示符,其中 namespace 为名字空间作用域
//建议不用这个指示符,可在需要的地方加 std 的作用域
void* operator new(size_t size) //size 代表总字节个数
{
void* ptr = malloc(size);
cout << "operator new: " << ptr << endl;
return ptr;
}
void operator delete(void* ptr)
{
cout << "operator delete: " << ptr << endl;
free(ptr);
}
int main()
{
int *p = new int;
delete p; //直接调用我们写好的 operator new(开辟空间) 和
//operator delete (释放空间),没有初始化和释放资源
return 0;
}
平时使用的 new 和 delete 有下面两个功能
new 1.开辟空间 2.初始化 delete 1.释放资源 2.释放空间
而这两个函数的功能为: operator new 开辟空间 operator delete 释放空间
思考:为什么要自己编写这两个函数?
new作为用户程序的关键字,调用系统开辟空间的接口,系统API交给一个文件或者管理系统,操控底层的硬件资源BSP。
所以new的过程是从用户态到内核态,其缺点一 :效率低;
如果申请3个字节,系统将分配4个字节,导致1个字节不可用,所以频繁调用易产生碎片,这是缺点二。
所以这两个函数 operator new ,operator delete 实现了一个自己的内存管理方案(即内存池。池:一组资源的集合)
内存池:怎样把资源分配出去?怎样把资源回收回来?内存池的设计如下:
//结合链队写一个简单内存池(意义不大) 之后再写一个通用内存池
const int MEM_POOL_SIZE = 10;
template<typename T>
class Queue//只有在new QueueItem()才会开辟内存池
{
public:
Queue()
{
pfront = prear = new QueueItem(0);
}
~Queue()//链怎么释放节点
{
QueueItem* pCur = pfront;
QueueItem* pNext = pfront;
while(pCur != NULL)
{
pNext = pCur->pnext;
delete pCur;
pCur = pNext;
}
pfront = prear = NULL;
}
void push(T val)//入队
{
QueueItem* pnewnode = new QueueItem(val);
prear->pnext = pnewnode;
prear = pnewnode;
}
void pop()//出队
{
if(!IsEmpty())
{
QueueItem* pCur = pfront->pnext;//有头结点,pCur指向第一个数据节点
pfront->pnext = pCur->pnext;//让头结点指向第二个数据节点
delete pCur;
}
}
T front()//获取队头元素
{
if(!IsEmpty())
{
return pfront->pnext->mdata;
}
}
T back()//获取队尾元素
{
if(!IsEmpty())
{
return prear->mdata;
}
}
private:
bool IsEmpty()
{
return pfront == prear;
}
class QueueItem
{
public:
QueueItem(T val = T()):mdata(val),pnext(NULL){}
void* operator new(size_t size)
{
if(pool == NULL)
{
pool = (QueueItem*)new char[size * MEM_POOL_SIZE];
QueueItem* pCur = pool;
for(pCur;pCur < pool + MEM_POOL_SIZE - 1;pCur++)
{
pCur->pnext = pCur + 1;
}
pCur->pnext = NULL;
}
QueueItem* rt = pool;
pool = pool->pnext;
return rt;
}
void operator delete(void* ptr)
{
if(NULL == ptr)
{
return;
}
QueueItem* p = (QueueItem*)ptr;
p->pnext = pool;
pool = p;
}
public:
T mdata;//数据域
QueueItem* pnext;//指针域
static QueueItem* pool;
};
QueueItem* pfront;//队头指针
QueueItem* prear;//队尾指针
};
template<typename T>
typename Queue<T>::QueueItem* Queue<T>::QueueItem::pool = NULL;//静态变量一定在类外初始
// QueueItem类型(加关键字typename) QueueItem 是普通的类,不需要加模板类型参数
int main()
{
Queue<int> que;
for(int i = 0;i < 10;i++)
{
que.push(i+1);
}
return 0;
}