定制new和delete

在看《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 address
		tmp_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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值