当前位置:编程学习 > C/C++ >>

第18章 特殊工具与技术(5)

18.1.7 一个内存分配器基类

需要怎样改进内置库的new和delete函数?一个通用策略是预先分配一块原始内存来保存未构造的对象,创建新元素的时候,可以在一个预先分配的对象中构造;释放元素的时候,将它们放回预先分配的块中,而不是将内存实际返还给系统。这种策略常被称为维持一个自由列表(freelist)。可以将自由列表实现为已分配但未构造的对象的链表。

1. CachedObj


template<class T> 
class CachedObj{ 
public: 
    void *operator new(size_t); 
    void operator delete(void*,size_t); 
    virtual ~CachedObj(){} 
protected: 
    T *next; 
private: 
    static void add_to_freelist(T*); 
    static std::allocator<T> alloc_mem; 
    static T *freestore; 
    static const void std::size_t chunk; 
}; 
template<class T>
class CachedObj{
public:
 void *operator new(size_t);
 void operator delete(void*,size_t);
 virtual ~CachedObj(){}
protected:
 T *next;
private:
 static void add_to_freelist(T*);
 static std::allocator<T> alloc_mem;
 static T *freestore;
 static const void std::size_t chunk;
};2. 使用CachedObj


template<class T> 
class QueueItem1:public CachedObj<QueueItem1<T>>{}; 
template<class T>
class QueueItem1:public CachedObj<QueueItem1<T>>{};3. 分配怎样工作


QueueItem1<int> *qi=new QueueItem1<int>(); 
 QueueItem1<int> *qi=new QueueItem1<int>();因为我们从CachedObj类派生QueueItem类,任何使用new表达式的分配,都分配并构造一个新的QueueItem对象。每个表达式:

(1)使用 QueueItem<T>::operator new函数从自由列表分配一个对象。

(2)为类型T使用元素类型的复制构造函数,在该内存中构造一个对象。

类似地,当像delete pt;这样删除一个QueueItem指针的时候,运行QueueItem析构函数清除pt指向的对象,并调用该类的operator delete,将元素所用的内存放回自由列表。

4. 定义operator new


template<class T> 
void *CachedObj<T>::operator new(size_t sz){ 
    if(sz!=sizeof(T)) 
        throw std::runtime_error("CachedObj:wrong size object in operator new"); 
    if(!freestore){ 
        T *arr=alloc_mem.allocate(chunk); 
        for(size_t i=0;i!=chunk;++i) 
            add_to_freelist(&arr[i]); 
    } 
    T *p=freestore; 
    freestore=freestore->CachedObj<T>::next; 
    return p; 

template<class T>
void *CachedObj<T>::operator new(size_t sz){
 if(sz!=sizeof(T))
  throw std::runtime_error("CachedObj:wrong size object in operator new");
 if(!freestore){
  T *arr=alloc_mem.allocate(chunk);
  for(size_t i=0;i!=chunk;++i)
   add_to_freelist(&arr[i]);
 }
 T *p=freestore;
 freestore=freestore->CachedObj<T>::next;
 return p;
}5. 定义operator delete

operator delete成员只负责管理内存,在析构函数中已经清楚了对象本身,delete表达式在调用operator delete之前调用析构函数。它调用add_to_freelist成员将被删除对象放回自由列表。


template<class T> 
void CachedObj<T>::operator delete(void* p, size_t){ 
    if(p!=0) 
        add_to_freelist(static_cast<T*>(p)); 

template<class T>
void CachedObj<T>::operator delete(void* p, size_t){
 if(p!=0)
  add_to_freelist(static_cast<T*>(p));
}6. add_to_freelist成员


template<class T> 
void CachedObj<T>::add_to_freelist(T *p){ 
    p->CachedObj<T>::next=freestore; 
    freestore=p; 

template<class T>
void CachedObj<T>::add_to_freelist(T *p){
 p->CachedObj<T>::next=freestore;
 freestore=p;
}为了避免任何与派生类中定义的成员可能的冲突,显式指定我们正在给基类成员next赋值。

7. 定义静态数据成员


template<class T> 
std::allocator<T> CachedObj<T>::alloc_mem; 
 
template<class T> 
T *CachedObj<T>::freestore=0; 
 
template<class T> 
const std::size_t CachedObj<T>::chunk=24; 

摘自 xufei96的专栏
 

补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,