程序中有时候会遇到这种情况,就是需要不停的去分配以及释放内存。带来的是不停的调用new以及delete带来的开销。
而且由于全局的new以及delete往往对多线程做出了并发保护,所以在单线程情况下这更带来一种浪费,一般的情况下是去实现一个
单线程的内存池来进行性能优化,配合所需的类往往带来很好的性能提升。
首先是作为内存池的模板类:
1 template<class T> 2 class MemoryPool{ 3 public: 4 MemoryPool(size_t size = EXPANSION_SIZE); 5 ~MemoryPool(); 6 7 //从空闲列表中分配T大小的空间 8 inline void * alloc(size_t size); 9 10 //释放内存到空闲列表中 11 inline void free(void * elements); 12 private: 13 MemoryPool<T> * next; //空闲列表的下一个元素 14 enum { EXPANSION_SIZE = 32 }; 15 void expandTheFreeList(int howMany = EXPANSION_SIZE); 16 }; 17 18 template<class T> 19 MemoryPool<T>::MemoryPool(size_t size) 20 { 21 expandTheFreeList(size); 22 } 23 24 template<class T> 25 MemoryPool<T>::~MemoryPool() 26 { 27 MemoryPool<T> * nextPtr = next; 28 if (next){ 29 for (nextPtr = next; nextPtr != nullptr; nextPtr = next){ 30 next = next->next; 31 delete[] ((char * )nextPtr); //这里的强制类型转换应该注意,不转换编译无法通过的当时分配 32 //内存的时候是按照char类型分配的,那么释放的时候也应该同样释放。 33 } 34 } 35 } 36 37 38 template<class T> 39 inline 40 void * MemoryPool<T>::alloc(size_t) 41 { 42 if (!next) 43 expandTheFreeList(); 44 MemoryPool<T> * head = next; 45 next = head->next;//分配了一块空间 46 return head; 47 } 48 49 template<class T> 50 inline 51 void MemoryPool<T>::free(void * doomed) 52 { 53 MemoryPool<T> * head = static_cast<MemoryPool<T> *>(doomed); 54 head->next = next; 55 next = head; 56 } 57 58 template<class T> 59 void MemoryPool<T>::expandTheFreeList(int howMany) 60 { 61 //保证分配的内存大小至少应该是大于指针大小或者是元素大小中的 最大者,因为二者之间是共享内存的 62 size_t sizeAlloc = (sizeof(T) > sizeof(MemoryPool<T> *)) ? 63 sizeof(T) : sizeof(MemoryPool<T> *); 64 MemoryPool<T> * runner = (MemoryPool<T>*)(new char[sizeAlloc]); //这里实际上是可以使用static_cast的,但是不知道为什么, 65 next = runner; //gcc下编译不能通过。可能因为gcc的限制比较严格。无奈,只能使用普通的强制类型转换 66 for (int i = 0; i < howMany; ++i){ 67 runner->next = (MemoryPool<T>*)(new char[sizeAlloc]); 68 runner = runner->next; 69 } 70 runner->next = 0; 71 }
下面是使用该内存池的一个rational类,代码如下:
1 class Rational{ 2 public: 3 Rational(int a = 0, int b = 1):n(a), d(b){} 4 void * operator new(size_t size){return memPool->alloc(size); } 5 void operator delete(void * doomed, size_t size){memPool->free(doomed);} 6 static void newMemPool(){memPool = new MemoryPool<Rational>; } 7 static void deleteMemPool() 8 { 9 if(!memPool) 10 return; 11 delete memPool; 12 } 13 private: 14 int n; 15 int d; 16 static MemoryPool <Rational> * memPool; 17 };
使用代码如下:
1 MemoryPool<Rational> * Rational::memPool = 0; 2 3 int main() 4 { 5 Rational * array[10]; 6 Rational::newMemPool(); 7 for(int j = 0; j < 2; ++j){ 8 for(int i = 0; i < 10; i++){ 9 array[i] = new Rational(i); 10 } 11 for(int i = 0; i < 10; i++){ 12 delete array[i]; 13 } 14 } 15 Rational::deleteMemPool(); 16 }