一般来说,使用堆来动态分配内存是常用的方式。然而,如果不断申请堆,会造成内存碎片,以至于由于堆本身大小的限制,难以再申请出连续空间的堆,显然造成了内存利用不合理。所以,有必要对内存申请进行一些管理。对于大型程序来说,很必要,提前申请一定量的堆,一定比不断申请快很多。使用数组方式,可以很快检索到可用的空间,并O(1)进行存取,而节点做成链表结构,更可以在O(1)释放某个空间之后找到合适的节点进行分配。
代码如下:
#ifndef SPACEPOOL_HHH
#define SPACEPOOL_HHH
//declaration;
template<typename T>
class CSpacePool;
template<typename T>
struct SPoolNode{
// members;
private:
T m_nData;
int m_nNextIndex;
public:
// constructors;
friend class CSpacePool<T>;
}; //SPoolNode;
template<typename T>
class CSpacePool{
private:
// members;
int m_nSpaceSize; // max number of nodes could be allocated;
int m_nFirstUseableIndex; // the first useable node.
SPoolNode<T>* m_pNode; // data table;
public:
// constructors;
CSpacePool(int maxsize);
~CSpacePool();
// methods;
int mAllocate(); // allocate a space;
void mDeAllocate(int& i); // deallocate the (i+1)th node;
}; // CSpacePool;
// de-constructors;
template<typename T>
CSpacePool<T>::CSpacePool(int maxsize = 100){
m_nSpaceSize = maxsize;
m_pNode = new SPoolNode<T>[m_nSpaceSize];
for(int i = 0; i < m_nSpaceSize - 1; i ++){
m_pNode[i].m_nNextIndex = i + 1;
}
m_pNode[m_nSpaceSize - 1].m_nNextIndex = -1;
m_nFirstUseableIndex = 0;
}
template<typename T>
CSpacePool<T>::~CSpacePool(){
delete[] m_pNode;
}
template<typename T>
int CSpacePool<T>::mAllocate(){
if(-1 == m_nFirstUseableIndex){
printf("Space is full, Cannot alloc\n");
return -1;
}else{
int ret = m_nFirstUseableIndex;
m_nFirstUseableIndex = m_pNode[m_nFirstUseableIndex].m_nNextIndex;
return m_nFirstUseableIndex;
}
}
template<typename T>
void CSpacePool<T>::mDeAllocate(int& i){
m_pNode[i].m_nNextIndex = m_nFirstUseableIndex;
m_nFirstUseableIndex = i;
i = -1;
}
#endif
测试代码如下:
#include "SimulatePointer.h"
#include <iostream>
#include <stdlib.h>
using namespace std;
int main(){
CSpacePool<int> pool(100);
for(int i = 0; i < 101; i ++)
pool.mAllocate();
for(int i = 0; i < 101; i ++){
int m = i;
pool.mDeAllocate(m);
}
system("pause");
return 0;
}
结果如下:
Space is full, Cannot alloc
请按任意键继续. . .
上述是最简单的内存池技术,实际上内存管理比这个复杂很多,但基本思想一致。事实上,在现在的大型程序里面,池技术是一个很重要的话题,例如线程池,进程池等资源池。它们能够有效避免多次分配带来的内核交互代价,进而加快程序速度。