前文我们介绍了简易版内存池的实现,但是那个代码看起来过于繁琐,不够清爽。我们可以把内存池的各个操作封装起来,作为一个独立的内存池使用。
(1)内存池独立出来为一个类。
(2)这个类的对象作为静态成员,定义于需要使用内存池的类中。作为静态成员的意义在于:不同的对象可以公用一个内存池。
(3)内存池使用嵌入式指针,减少指针的内存损耗。
(4)重载使用内存池的类的operator new函数和operator delete函数。
#include
using namespace std;
class Allocator
{
private:
struct obj{
struct obj * next; //嵌入式指针
};
obj * freeList = nullptr;
const int length = 5; //一个内存的大小是5
public:
void * allocate(size_t size){
obj * p ;
if(freeList== nullptr){
freeList = (obj*)malloc(size*length);
p = freeList;
for(int i=0;i<length-1;i++){
p->next = (obj* )((char*)p+size); //内存切片
p=p->next;
}
p->next = nullptr;
}
p = freeList;
freeList = freeList ->next;
return p;
}
void deallocate(void * p){
((obj*)p)->next = freeList;
freeList = (obj*)p;
}
};
class A{
int a;
int b;
static Allocator allocator;
public:
A(int a ,int b ):a(a),b(b){}
void * operator new(size_t size){
return allocator.allocate(size);
}
void operator delete (void * p){
allocator.deallocate(p);
}
};
Allocator A::allocator;
int main()
{
for(int i=0;i<15;i++){
A * a = new A(1,2);
cout<<a<<endl;
if((i+1)%5 == 0){
cout<<endl;
}
}
}
内存池的大小是5,如果打印出来的结果中,五个地址为一组,一组内部之间相差8字节。组与组之间相差的字节数不一定,那么说明我们的内存池成功了。
运行结果:
0x1801d5118e0
0x1801d5118e8
0x1801d5118f0
0x1801d5118f8
0x1801d511900
0x1801d511c50
0x1801d511c58
0x1801d511c60
0x1801d511c68
0x1801d511c70
0x1801d511c80
0x1801d511c88
0x1801d511c90
0x1801d511c98
0x1801d511ca0
成功了。