内存分配(2)–embedded pointer

到现在看来,简单的空闲链表的主要开销就是一个next指针域,在32位系统上是4个字节。可是如果我们的CMyObject本来就很小,只有4个字节,那额外开销可就是100%阿,如果系统中用到几万,十几万,甚至上百万个CMyObject,就不容小视了!
我们仔细来分析一下刚才的例子,什么时候会用到next指针呢?
1. 第一次分配对象,建立整个freeStore的链表的时候,初始化各个实例的next指针
2. 每次给申请者一个实例时,要修改freeStore = freeStore->next
3. 每次归还一个实例时,链表插入操作要用到next.
这里我们的一个观察是,next指针的使用都是在申请和归还的时候,也就是说申请者在使用这块内存的时候从来都不需要next!既然next指针所占的4个字节不会被同时使用,那我们是不是可以想一个办法,让使用时和申请/归还重用同一块内存呢。感谢C语言的union,给了我们实现的可能性。
class CMyObject
{
private:
 struct CMyObjectRep{
  int   _data1;
              char  _data2;
 };
private:
 //注意,这里是个匿名的union,我们把使用期的成员变量都放在一个结构里面
      union{
         CMyObjectRep rep;  // 使用期会用到的成员变量
         CMyObject* next;   // 分配,归还时使用的,服务于空闲链表操作
 };
public:
     //其他都和简单的空闲链表的实现一模一样
};
void* CMyObject::operator new(size_t size)的实现也和上一篇中提到的实现一模一样,这里就不重复了。
看来现在的实现不错了哦-:)分配性能也提高了,也没有额外的开销,但是问题是,如果现在有了一个新的叫做CYourObject的类,他也想使用这样的分配策略,我们就要为CYourObject重写刚才所有的代码,以后又有CHisObject,CHerObject呢…?!怎么办?我们得把这些代码抽出来,给大家用!我们来考虑一下,我初步的打算是写一个CAlloc的类,我们来分析一下需求:
1.这个类至少知道实例的大小,例如sizeof(CMyObject);我们可以使用模板,也可以由参数输入
2.链表的初始化长度(这个可以系统预设,也可以由参数输入)
3.这个类是服务于类而不是服务于实例,所以应该是被服务类的静态成员变量。
template <class T>
class CAlloc{
public:
     // 分配大小为n的内存,一般n应该等于sizeof(T)
     T* allocate(size_t n);
     // 归还大小为n的内存
   void deallocate(T* p,size_t n);
public:
    // 初始化空闲链表的大小
    CAlloc(size_t n = 512);
 
    // 释放CAlloc<T>中维护的所有内存
     ~  CAlloc(); 
};
class CMyObject
{
private:
    static CAlloc<CMyObject> memPool;
};
CAlloc<CMyObject> CMyObject::memPool(512);
inline void* CMyObject::operator new(size_t size)
{
 return memPool.allocate(size);
}
inline void CMyObject::operator delete(void* p, size_t size)
{
 memPool.deallocate(p,size);
}
是不是干净很多呢,实际上还可以使用宏展开把那些个 声明和定义都简化了。MFC就是这么干的,我也来学一把,哈哈:
#define DECLARE_ALLOC(class_name)
public:
 void* operator new(size_t size)  {  return memPool.allocate(size); }
       void  operatoe delete(void* p, size_t size) { return memPool.deallocate(p,size); }
private:
       static CAlloc<class_name> memPool;
#define IMPLEMENT_ALLOC(class_name, block_size)
CAlloc<class_name> class_name::memPool(block_size);
 
嘿嘿,现在我们来写写CYourObject -:)
class CYourObject{
 DECLARE_ALLOC(CYourObject)
public:
};
IMPLEMENT_ALLOC(CYourObject,512)
恩,现在就差不多了~~ 不过还有更精巧的,下一次我们看真正的SGI的内存分配实现~~


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值