標籤:
基於 http://www.cnblogs.com/diegodu/p/4555018.html operator new的知識基礎上 介紹這個章節的內容
對於一般直接 new 與delete 效能較差,可以自己管理寫記憶體的申請與釋放。其實一般的operator new 和operator delete 直接調用 malloc 和 free的。
版本0:
class Rational{public: Rational(int a=0, int b =1 ): n(a),d(b){}private: int n; int d;};
版本1:專用的記憶體管理器
#include <stddef.h> // for size_t#include <iostream>using namespace std;class NextOnFreeList { public: NextOnFreeList *next;};class Rational { public: Rational (int a = 0, int b = 1 ) : n(a), d(b) {} inline void *operator new(size_t size); inline void operator delete(void *doomed, size_t size); static void newMemPool() { expandTheFreeList(); } static void deleteMemPool(); private: static NextOnFreeList *freeList; // A free list of Rational objects. static void expandTheFreeList(); enum { EXPANSION_SIZE = 32}; int n; // Numerator int d; // Denominator};inlinevoid * Rational::operator new(size_t size){ if (0 == freeList) {// If the list is empty, fill it up. expandTheFreeList(); } NextOnFreeList *head = freeList; freeList = head->next; return head;}inlinevoid Rational::operator delete(void *doomed, size_t size){ NextOnFreeList *head = static_cast <NextOnFreeList *> (doomed); head->next = freeList; freeList = head;}void Rational::expandTheFreeList(){ // We must allocate an object large enough to contain the next // pointer. size_t size = (sizeof(Rational) > sizeof(NextOnFreeList *)) ? sizeof(Rational) : sizeof(NextOnFreeList *);// NextOnFreeList *runner = static_cast <NextOnFreeList *>(new char[size]); NextOnFreeList *runner = (NextOnFreeList *)(new char[size]); freeList = runner; for (int i = 0; i < EXPANSION_SIZE; i++) { //runner->next = static_cast <NextOnFreeList *> (new char[size]); runner->next = (NextOnFreeList *)(new char[size]); runner = runner->next; } runner->next = 0; cout << "expand" << endl;}void Rational::deleteMemPool(){ NextOnFreeList *nextPtr; for (nextPtr = freeList; nextPtr != NULL; nextPtr = freeList) { freeList = freeList->next; delete [] nextPtr; }}//測試codeNextOnFreeList *Rational::freeList = 0;int main(){ Rational *array[1000]; Rational::newMemPool(); // Start timing here for (int j = 0; j < 500; j++) { for (int i = 0; i < 1000; i++) { array[i] = new Rational(i); } for (int i = 0; i < 1000; i++) { delete array[i]; } } // Stop timing here Rational::deleteMemPool(); return 0;}
這版本是通過重載 目標類 中的new 與delete 實現記憶體管理,只適用於目標類,但是速度是最快的。
實現方式是維護一個鏈表,類中靜態聲明鏈表頭,鏈表維護一串空間,通過類型轉換在 目標類 和 鏈表指標 之間轉換。
如果記憶體不夠(freelist=NULL)是一次申請較多記憶體進行維護。
鏈表的添加刪除(對於函數釋放空間與申請空間)是在鏈首操作。
書上47 行 52行通過 靜態類型轉換不成功,改為了 強制轉換,在 g++ 中能夠編譯運行。
主要在主函數中調用靜態函數 鏈表的申請與釋放。
版本2:固定大小對象的記憶體池
考慮版本1,可以通過模板實現管理特定的對象。最主要的參數是類的大小。
實現是專門聲明一個管理記憶體的記憶體池類,使用模板實現,提供alloc() free() 介面,給類申請與釋放記憶體。
記憶體池類的實現是自身有一個MemoryPool<T>* next 指標用來指向維護的鏈表,記憶體的操作都在鏈首位置。
#include <stddef.h>#include <iostream>using namespace std;template <class T>class MemoryPool { public: MemoryPool (size_t size = EXPANSION_SIZE); ~MemoryPool (); // Allocate a T element from the free list. inline void* alloc (size_t size); // Return a T element to the free list. inline void free (void *someElement); private: // next element on the free list. MemoryPool<T> *next; // If the freeList is empty, expand it by this amount. enum { EXPANSION_SIZE = 32}; // Add free elements to the free list void expandTheFreeList(int howMany = EXPANSION_SIZE);};template <class T>MemoryPool <T> :: MemoryPool (size_t size){ expandTheFreeList(size);} template < class T > MemoryPool < T > :: ~MemoryPool (){ MemoryPool<T> *nextPtr = next; for (nextPtr = next; nextPtr != NULL; nextPtr = next) { next = next->next; cout << nextPtr << endl; //delete [] nextPtr; //delete nextPtr; delete [](char*)nextPtr; //不太明白為什麼這樣是對的,上面的方法不行。。
//明白了,因為new的時候就是用char位元組的方法申請的,delete的時候要對應。。
}}template < class T > inlinevoid* MemoryPool < T > :: alloc (size_t){ if (!next) { expandTheFreeList(); } MemoryPool<T> *head = next; next = head->next; return head;}template < class T > inlinevoid MemoryPool < T > :: free (void *doomed){ MemoryPool<T> *head = static_cast <MemoryPool<T> *> (doomed); head->next = next; next = head;} template < class T >void MemoryPool < T > :: expandTheFreeList(int howMany){ // We must allocate an object large enough to contain the // next pointer. size_t size = (sizeof(T) > sizeof(MemoryPool<T> *)) ? sizeof(T) : sizeof(MemoryPool<T> *); //MemoryPool<T> *runner = static_cast <MemoryPool<T> *>(new char [size]); MemoryPool<T> *runner = (MemoryPool<T> *)(new char [size]); next = runner; for (int i = 0; i < howMany ; i++) { //runner->next = static_cast <MemoryPool<T> *> new char [size]; runner->next = (MemoryPool<T> *)( new char [size]); runner = runner->next; } runner->next = NULL;}class Rational { public: Rational (int a = 0, int b = 1 ) : n(a), d(b) {} void *operator new(size_t size) { return memPool->alloc(size); } void operator delete(void *doomed,size_t size) { memPool->free(doomed); } static void newMemPool() { memPool = new MemoryPool <Rational>; } static void deleteMemPool() { delete memPool; } private: int n; // Numerator int d; // Denominator static MemoryPool <Rational> *memPool;};MemoryPool <Rational> *Rational::memPool = 0;int main(){ Rational *array[1000]; Rational::newMemPool(); // Start timing here for (int j = 0; j < 500; j++) { for (int i = 0; i < 1000; i++) { array[i] = new Rational(i); } for (int i = 0; i < 1000; i++) { delete array[i]; } } // Stop timing here Rational::deleteMemPool();}
efficient c++,單線程記憶體池