引言
使用 new expression 为类的多个实例分配动态内存时,cookie导致内存利用率可能不高,此时我们通过实现类的 内存池 来降低overhead。从不成熟到巧妙优化的内存池,得益于union的 分时复用 特性,内存利用率得到了提高。
原因
在实例化某个类的对象时(在heap而不是stack中),若不使用 array new ,则每次实例化时都要调用一次内存分配函数,类的每个实例在内存中都有上下两个cookie,从而降低了内存的利用率。然而, array new 也有 先天的缺陷 ,即只能调用默认无参构造函数,这对于很多没有提供无参构造函数的类来说是不合适的。
因此,我们可以对于一个没有实例化的类第一次实例化时,先分配一大块内存(内存池),这一大块内存记录在类中,只有上下两个cookie,能够容纳多个实例。后续实例化时,若内存池中还有剩余内存,则不必申请内存分配,只在内存池中分配。内存回收时,将实例所占用的内存回收到内存池中。若内存池中无内存,则再申请分配大块内存。
我们以链表的形式组织内存池,内存池中每个一个链表是一个小桶,这个桶中装我们实例化的对象。
内存池链表的头结点记录在类中,即以class staic变量的形式存储。组织形式如下:
实现代码如下:
#include <iostream>
using namespace std;
class DemoClass{
public:
DemoClass() = default;
DemoClass(int i):data(i){}
static void* operator new(size_t size);
static void operator delete(void *);
virtual ~DemoClass(){}
private:
DemoClass *next;
int data;
static DemoClass *freeMemHeader;
static const size_t POOL_SIZE;
};
DemoClass * DemoClass::freeMemHeader = nullptr;
const size_t DemoClass::POOL_SIZE = 24;//设定内存池能容纳24个DemoClass对象
void* DemoClass::operator new(size_t size){
DemoClass* p;
if(!freeMemHeader){//freeMemHeader为空,内存池中无空间,分配内存
size_t pool_mem_by