分配固定大小对象的内存池
//下面的代码思想取自efficient c++
1 ////////////////////////////////////////////////////////////////////////// 2 //可分为:1.内存池本身的创建和删除 3 // 2.内存池中空闲内存的维护 4 //两个部分区分开,逻辑就清晰了。 5 //by wangpei 2015.1.4 6 ///////////////////////////////////////////////////////////////////////// 7 template <typename T> 8 class MemoryPool{ 9 public: 10 MemoryPool(size_t size = EXSIZE); 11 ~MemoryPool(); 12 inline void* alloca(size_t size); 13 inline void free(void *element); 14 private: 15 enum {EXSIZE = 32}; 16 MemoryPool<T> *next; 17 void expand(size_t s = EXSIZE); 18 }; 19 template<typename T> 20 MemoryPool<T>::MemoryPool(size_t size) 21 { 22 expand(size); 23 } 24 25 template<typename T> 26 MemoryPool<T>::~MemoryPool() 27 { 28 MemoryPool<T> * ptr; 29 while (next){ 30 ptr = next->next; 31 delete[] freeNode; //指针指向了正确的初始位置,就能够正确的释放空间 32 de++; 33 next = ptr; 34 } 35 } 36 37 template<typename T> 38 inline void* MemoryPool<T>::alloca(size_t size) 39 { 40 if (next == 0) 41 expland(); 42 MemoryPool<T>* currentFree = next; 43 next = next->next; 44 return currentFree; 45 } 46 47 template<typename T> 48 inline void MemoryPool<T>::free(void *element) 49 { 50 MemoryPool<T>* head = static_cast<MemoryPool<T>* >(doomed); //注意此处的链表维护,不能让链表断开了 51 head->next = next; 52 next = head; 53 } 54 55 template<typename T> 56 void MemoryPool<T>::expand(size_t s) 57 { 58 const size_t s = (sizeof(MemoryPool<T>*) >= sizeof(T)) ? sizeof(MemoryPool<T>*) : sizeof(T);//这里是关键,根据类型的大小确定堆大小 59 MemoryPool<T>* head = (MemoryPool<T>*)new char[s]; //将char*强制转换为MemoryPool<T>* 可读性很差,但却高效的利用了内存空间 60 ma++; 61 head->next = next; 62 freeNode = head; 63 for (size_t i = 0; i < EXPANSION; i++){ 64 head = (MemoryPool<T>*)new char[s]; 65 ma++; 66 head->next = next; 67 next = head; 68 } 69 } 70 class Rational_tem{ 71 private: 72 static MemoryPool<Rational_tem> * memPool; 73 int n; 74 int d; 75 public: 76 Rational_tem(int a = 0, int b = 1) :n(a), d(b){} 77 void* operator new (size_t s) 78 { 79 return memPool->alloca(s); 80 } 81 void operator delete(void* doomed, size_t s) 82 { 83 return memPool->free(doomed); 84 } 85 static void newMemPool() 86 { 87 memPool = new MemoryPool < Rational_tem > ; 88 } 89 static void deleteMemPool() 90 { 91 delete memPool; 92 } 93 };
有个地方需要注意:内存池不保证分配出去的内存都能够回收,所有new的对象,必须delete后,才能够正确的回收。所以,内存池销毁时,是通过从链表头开始向下释放资源。
该内存池应用在Rational_tem这样的类大量new、delete,在短时间重复数量越多,提升的速度越快。