基于 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 }; inline void * 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; } inline void 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; } } //测试code NextOnFreeList *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 > inline void* MemoryPool < T > :: alloc (size_t) { if (!next) { expandTheFreeList(); } MemoryPool<T> *head = next; next = head->next; return head; } template < class T > inline void 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(); }
时间: 2024-10-19 02:05:15