一、使用内存池背景
1、应用程序频繁地在堆上分配和释放内存,会导致性能的损失,会使系统中出现大量的内存碎片,降低内存的利用率;
2、默认的分配和释放内存算法自然也考虑了性能,然而这些内存管理算法的通用版本为了应付更复杂、更广泛的情况,需要做更多的额外工作;
3、而对于某一个具体的应用程序来说,适合自身特定的内存分配释放模式的自定义内存池可以获得更好的性能;
二、代码实现
(1)先申请一块连续的内存空间,该段内存空间能够容纳一定数量的对象;
(2)每个对象连同一个指向下一个对象的指针一起构成一个内存节点(Memory Node)。各个空闲的内存节点通过指针形成一个链表,链表的每一个内存节点都是一块可供分配的内存空间;
(3)某个内存节点一旦分配出去,从空闲内存节点链表中去除;
(4)一旦释放了某个内存节点的空间,又将该节点重新加入空闲内存节点链表;
(5)如果一个内存块的所有内存节点分配完毕,若程序继续申请新的对象空间,则会再次申请一个内存块来容纳新的对象。新申请的内存块会加入内存块链表中。
#include <iostream>
using namespace std;
template <int ObjectSize, int NumofObjects = 20>
class MemPool {
private:
/*空闲节点结构体*/
struct FreeNode {
FreeNode* pNext;
char data[ObjectSize];
};
/*内存块结构体*/
struct MemBlock {
MemBlock* pNext;
FreeNode data[NumofObjects];
};
FreeNode* freeNodeHeader;
MemBlock* memBlockHeader;
public:
MemPool() {
freeNodeHeader = NULL;
memBlockHeader = NULL;
}
~MemPool() {
MemBlock* memBlockPtr;
while (memBlockHeader) {
memBlockPtr = memBlockHeader->pNext;
delete memBlockHeader;
memBlockHeader = memBlockPtr;
}
}
void* malloc();
void free(void*);
};
template <int ObjectSize, int NumofObjects>
void* MemPool <ObjectSize, NumofObjects>::malloc() {
if (freeNodeHeader == NULL) {/*无空闲节点,申请新内存块*/
MemBlock* newMemBlock = new MemBlock;
newMemBlock->pNext = NULL;
freeNodeHeader = &newMemBlock->data[0];/*设置内存块的第一个节点为空闲节点*/
for (int i = 1; i < NumofObjects; ++i) {
newMemBlock->data[i - 1].pNext = &newMemBlock->data[i];
}
newMemBlock->data[NumofObjects - 1].pNext = NULL;
if (memBlockHeader == NULL) {
memBlockHeader = newMemBlock;
}
else {
newMemBlock->pNext = memBlockHeader;
memBlockHeader = newMemBlock;
}
}
void* freeNode = freeNodeHeader;
freeNodeHeader = freeNodeHeader->pNext;
return freeNode;
}
template <int ObjectSize, int NumofObjects>
void MemPool <ObjectSize, NumofObjects>::free(void* p) {
FreeNode* pNode = (FreeNode*)p;
pNode->pNext = freeNodeHeader;/*将释放的节点插入到空闲节点头部*/
freeNodeHeader = pNode;
}
class DemonstratorClass {
private:
static int count;
int No;
public:
DemonstratorClass() {
No = count;
count++;
}
void print() {
cout << this << ":";
cout << "the " << No << "th object" << endl;
}
void* operator new(size_t size);
void operator delete(void* p);
};
MemPool <sizeof(DemonstratorClass), 20> mp;
void* DemonstratorClass::operator new(size_t size) {
return mp.malloc();
}
void DemonstratorClass::operator delete(void* p) {
mp.free(p);
}
int DemonstratorClass::count = 0;
int main() {
DemonstratorClass* p1 = new DemonstratorClass;
p1->print();
DemonstratorClass* p2 = new DemonstratorClass;
p2->print();
delete p1;
p1 = new DemonstratorClass;
p1->print();
DemonstratorClass* p3 = new DemonstratorClass;
p3->print();
delete p1;
delete p2;
delete p3;
}
三 实验验证
0x562f349b8e78:the 0th object
0x562f349b8e88:the 1th object
0x562f349b8e78:the 2th object
0x562f349b8e98:the 3th object