大胖的部落格

Just a note

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  112 随笔 :: 0 文章 :: 3 评论 :: 0 Trackbacks

缺省版本的operator new在分配内存时,除了分配对象大小的内存外,还会额外分配一小块空间用来存放所分配内存的大小,这样 operator delete在释放内存时,才知道要释放内存的大小。
所以当对象的size很小时(例如只有一个指针大小),连续使用缺省的operator new来分配内存,会浪费很多额外空间用来存放所分配内存的大小。
因此我们可以通过重载operator new和operator delete来定义自己的内存分配方式,避免分配额外空间。

内存池:通过一次申请比较大的内存空间,来避免小空间内存的频繁申请和释放,每次需要为对象分配内存空间时,在已经申请的大空间内分配。
空闲区被按照对象大小划分为若干块,块与块之间通过链表组织起来。

示例代码:

//实现类声明
class ObjectImpl;

class Object
{
public:
    
//operator new
    static void* operator new(size_t size);

    
//operator delete
    static void operator delete(void *p, size_t size);

private:
    union 
    
{
        ObjectImpl 
*pObj;            //pointer to the ObjectImpl
        Object *pNext;                //pointer to the next object
    }
;

    
static const int obj_num;        //the number of object to be allocated
    static Object *free;            //pointer to the free space
}
;

const int Object::obj_num    = 20;
Object
* Object::free        = NULL;

void* Object::operator new(size_t size)
{
    
//判断请求的size是否与对象size相等
    if(size != sizeof(Object))
    
{
        
return ::operator new(size);
    }


    
//返回指针指向空闲区首地址
    Object *alloc = free;
    
//若空闲区没有空间,则分配内存;否则将空闲区指针向后移一个Object的size
    if(NULL == alloc)
    
{
        
//分配obj_num个对象需要的空间
        Object *= static_cast<Object*>(::operator new(obj_num*sizeof(Object)));
        
//将空闲区空间按链表形式划分成若干块
        for(int i=0; i<obj_num-1++i)
        
{
            p[i].pNext 
= &p[i+1];
        }

        
//最后一块的next指空
        p[obj_num-1].pNext = NULL;
        
//返回空闲区首地址
        alloc = p;
    }

    
//空闲区指针后移
    free = alloc->pNext;

    
return alloc;
}


void Object::operator delete(void *del, size_t size)
{
    
//判断要释放的空间是否合法
    if(NULL == del)
    
{
        
return;
    }


    
//判断请求的size是否与对象size相等
    if(size != sizeof(Object))
    
{
        ::
operator delete(del);
    }


    
//将要释放的空间插入空闲区链表前端
    Object *= static_cast<Object*>(del);
    p
->pNext = free;
    free 
= p;
}


总结:
1、new和delete的实现要配对。
2、delete要考虑传入空指针的情况。
3、new和delete需要考虑子类调用父类重载的operator的情况,这时需要释放的子类对象空间会比父类的大,应该调用全局operatoer。
4、表示申请内存空间大小和指向空闲区的成员应声明为static,这样才不会占用对象的空间。
5、使用union,当表示对象时,该union表示指向实现类对象的指针;否则,表示next指针,指向空闲区链表中的下一个空闲块。

     因为 只有当对象空间被解释为空闲区的时候,才需要为其提供链表的next指针。这样避免了额外扩充类的大小。

优点:
1、内存分配与释放速度变快。
2、不会产生内存碎片。
posted on 2009-05-22 14:43 大胖 阅读(1716) 评论(0)  编辑 收藏 引用 所属分类: C++

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理