定制new和delete

来源:互联网 发布:mac突然无法连接wifi 编辑:程序博客网 时间:2024/05/22 22:34
在看《effective C++》第8章(定制new和delete)时,发现自己对new和delete理解的并不是那么深刻。
为什么要定制new和delete呢,因为在某些环境下(嵌入式),定制的new和delete效率会更高。
我在之前的文章“重载new和delete检测内存泄漏”中也做过类似的总结。

下面的例子中重载了class-specific new和class-specific delete
  void* T::operator new  ( std::size_t count );
  void T::operator delete  ( void* ptr );
如果想使用定制的new和delete需要继承fixedSizeResourcePool类。  
总内存(使用了栈内存模拟)的大小固定,被平均分配成8个字节大小的内存块,每次new取其中一块,delete回收一块。
还是看代码吧。  

借用《effective C++》Item 50中的一句话:编写一个几乎能工作的自定义内存管理器相当容易,编写一个工作得很好的要困难得多。

#include <cstdio>using namespace std;typedef long unsigned int uint32_t;typedef unsigned char uint8_t;typedef unsigned char Alignment;typedef void* MemAddress;template<typename T, Alignment ALIGNMENT = 8>class fixedSizeResourcePool{public:  //根据输入,初始化一块内存  //iNumOfObjects:内存块数量  //address:内存起始位置  //name_p:内存名字  static void init(const int iNumOfObjects, const MemAddress address, const char * name_p)  {name_p_ = const_cast<char*>(name_p);uint8_t* currAddress = reinterpret_cast<uint8_t*>(address);for (int i = 0; i < iNumOfObjects; i++){    //做到8字节对齐,便于CPU快速寻址const uint8_t alignmentError = reinterpret_cast<uint32_t>(currAddress) %ALIGNMENT;  if (alignmentError != 0){   //去除多余位置   currAddress += (ALIGNMENT - alignmentError);}        //这里将内存分块:内存本身不变,poolInfo_.freeList_p_在变linkedList* tmp_p = reinterpret_cast<linkedList*>(currAddress);//point to currAddress addresstmp_p->next_p_ = poolInfo_.freeList_p_;                //poolInfo_.freeList_p_->next_p_ =  poolInfo_.freeList_p_;poolInfo_.freeList_p_ = tmp_p;        printf("init:: poolInfo_.freeList_p_ = %x \n",poolInfo_.freeList_p_);//将内存块按sizeof(T)的大小分块currAddress += sizeof(T);}poolInfo_.numOfObjects_ = iNumOfObjects;printf("fixedSizeResourcePool %s initialized with iNumOfObjects: %d, sizeof(T): %d, totalBuffer: %d, Address: 0x%08x, ALIGNMENT: %d \n",        name_p_, iNumOfObjects, sizeof(T), iNumOfObjects * sizeof(T), address, ALIGNMENT);  }  //重载operator new  static void *operator new(uint32_t size) throw()  {    linkedList* tmp_p = poolInfo_.freeList_p_;    if (tmp_p != 0)    {  printf("new:: poolInfo_.freeList_p_ = %x \n",poolInfo_.freeList_p_);  printf("new:: poolInfo_.freeList_p_->next_p_ = %x \n",poolInfo_.freeList_p_->next_p_);  //每次在链表中获取一块fixedSize的内存      poolInfo_.freeList_p_ = poolInfo_.freeList_p_->next_p_;      poolInfo_.numAllocatedObjects_++;      return tmp_p;    }    else     {   printf("no pool resource \n");       return 0;     }  }  //placement new  static void* operator new(uint32_t size, void *p)  {    return p;  }    //重载operator delete  static void operator delete(void * p)  {       //每次在链表中删除一块fixedSize的内存    linkedList* tmp_p = reinterpret_cast<linkedList*> (p);    tmp_p->next_p_ = poolInfo_.freeList_p_;    poolInfo_.freeList_p_ = tmp_p;    poolInfo_.numAllocatedObjects_--;       }  static inline int getNumFreeObjects()  {    return poolInfo_.numOfObjects_ - poolInfo_.numAllocatedObjects_;  }    class linkedList  {  private:    linkedList* next_p_;    friend class fixedSizeResourcePool;  };  struct poolInfo  {    linkedList*     freeList_p_;     //链表            int  numAllocatedObjects_;       //已分配内存块    int  numOfObjects_;              //总内存块  };  private:  static poolInfo poolInfo_;  static char* name_p_;protected:   fixedSizeResourcePool(void) {};   virtual ~fixedSizeResourcePool() {};}; template<typename T, Alignment ALIGNMENT>typename fixedSizeResourcePool<T, ALIGNMENT>::poolInfo fixedSizeResourcePool<T, ALIGNMENT>::poolInfo_ = {0, 0, 0}; template<typename T, Alignment ALIGNMENT>char* fixedSizeResourcePool<T, ALIGNMENT>::name_p_ = 0;  class myClass: public fixedSizeResourcePool<myClass, 8>{  public:  myClass():fixedSizeResourcePool<myClass>()  {  }};int main(){  const int num= 10;    //phyMem is sizeof(myClass)*num = 80 byte  //在栈内存的基础上分配内存  char phyMem[sizeof(myClass)*num];  myClass::init(num, phyMem, "phy_Mem" );    myClass *mO = new myClass;  myClass *mO2 = new myClass;  int n = fixedSizeResourcePool<myClass, 8>::getNumFreeObjects();  printf("After new, The memory left = %d \n", n);  delete mO;  delete mO2;  n = fixedSizeResourcePool<myClass, 8>::getNumFreeObjects();  printf("After delete, The memory left = %d \n", n);}


0 0
原创粉丝点击