程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 第18章 特殊工具與技術(5)

第18章 特殊工具與技術(5)

編輯:C++入門知識

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的專欄
 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved