用C++模板来展示new与delete操作符原理

C++中的new与delete可以认为是C中的malloc与free的升级版本。

new包含两部分,一部分是与malloc功能相同,是从堆上面申请内存块,第二部是调用类的构造方法来初始化刚申请的内存。

delete是new的逆过程,先调用类的析构方法来反初始化,再把刚申请的内存还给堆。

new [] 与delete []是针对数组操作符,要注意是通过new []分配的对象,不能用delete来释放对象,否则会有内存泄漏。当然通过new分配的对象,不能用delete[]来释放对象。后面我会通过代码来说明为什么。

 

下面是C++ 中的new与delete函数原型,申请内存失败会抛出异常bad_alloc

 

[cpp]  view plain copy
  1. void* operator new(std::size_tthrow (std::bad_alloc);  
  2. void* operator new[](std::size_tthrow (std::bad_alloc);  
  3. void operator delete(void*) throw();  
  4. void operator delete[](void*) throw();  

 

 使用举例

 

[cpp]  view plain copy
  1. int* p1 = new int();  
  2. delete p2;  
  3.   
  4. int* p2 = new int[5];  
  5. delete [] p2;  

 

 终于到了用模板来模拟new与delete操作符,代码中有注释说明,其中对于调用类的构造方法,采用一种C++标准中称作in-place construtor的方式。使用原型为T* = new(pbuff) T(),直译的话就是在pbuff这块内存构造T类,而不用再去堆上面申请内存。这种技巧大量应用在对象池的实现中,即pbuff这块内存可以挂在链表中反复地使用(这里先不展开说了)。

 

[cpp]  view plain copy
  1. /** 
  2.  * A simulation of c++ new T() & new T(param) operation 
  3.  */  
  4. struct NewObj  
  5. {  
  6.     template <typename T>  
  7.     inline void operator()(T*& pObj)  
  8.     {  
  9.         // allocate memory form heap  
  10.         void * pBuff = malloc(sizeof(T));  
  11.         // call constructor  
  12.         pObj = new (pBuff) T();  
  13.     }  
  14.   
  15.     template <typename T, typename P>  
  16.     inline void operator()(T*& pObj, const P& param)  
  17.     {  
  18.         // allocate memory form heap  
  19.         void * pBuff = malloc(sizeof(T));  
  20.         // call constructor, pass one param  
  21.         pObj = new(pBuff) T(param);  
  22.     }  
  23. };  
  24.   
  25. /** 
  26.  * A simulation of c++ delete T operation 
  27.  */  
  28. struct DeleteObj  
  29. {  
  30.     template <typename T>  
  31.     inline void operator()(T*& pObj)  
  32.     {  
  33.         if ( NULL == pObj ) { return ;}  
  34.         // call destructor  
  35.         pObj->~T();  
  36.         // free memory to heap  
  37.         free((void*)pObj);  
  38.         pObj = NULL;  
  39.     }  
  40. };  
  41.   
  42. /** 
  43.  * A simulation of c++ new T[N]() operation 
  44.  */  
  45. struct NewObjArray  
  46. {  
  47.     template <typename T>  
  48.     inline void operator()(T*& pObj, unsigned int size)  
  49.     {  
  50.         // save the number of array elements in the beginning of the space.  
  51.         long * pBuff = (long *) malloc (sizeof(T) * size + sizeof(long));  
  52.         *((unsigned int *) pBuff) = size;  
  53.         pBuff++;  
  54.   
  55.         // change pointer to T type, then can use pT++  
  56.         T * pT = (T *) pBuff;  
  57.         // save the pointer to the start of the array.  
  58.         pObj = pT;  
  59.         // now iterate and construct every object in place.  
  60.         for (unsigned int i = 0; i < size; i++)  
  61.         {  
  62.             new((void *) pT) T();  
  63.             pT++;  
  64.         }  
  65.     }  
  66. };  
  67.   
  68.   
  69. /** 
  70.  * A simulation of c++ delete [] T operation 
  71.  */  
  72. struct DeleteObjArray  
  73. {  
  74.     template <typename T>  
  75.     inline void operator()(T*& pObj)  
  76.     {  
  77.         unsigned int size = *((unsigned int *) ((long *) pObj - 1));  
  78.   
  79.         T * pT = pObj;  
  80.         // call destructor on every element in the array.  
  81.         for (unsigned int i = 0; i < size; i++)  
  82.         {  
  83.             pT->~T();  
  84.             pT++;  
  85.         }  
  86.         // free memory to heap.  
  87.         free ((void *) ((long *) pObj - 1));  
  88.         pObj = NULL;  
  89.     }  
  90. };  

 

 测试代码

 

[cpp]  view plain copy
  1. struct TestClass  
  2. {  
  3.     TestClass() : mem1(0), mem2(0)  {}  
  4.   
  5.     TestClass(int m) : mem1(m), mem2(0) {}  
  6.   
  7.     int mem1;  
  8.     long mem2;  
  9. };  
  10.   
  11. void test_new_delete()  
  12. {  
  13.     TestClass* p1 = NULL;  
  14.     NewObj()(p1);  
  15.     printf("%p/n", p1);  
  16.     DeleteObj()(p1);  
  17.   
  18.     //  
  19.     TestClass* p2 = NULL;  
  20.     NewObj()(p2, 0);  
  21.     printf("%p/n", p2);  
  22.     DeleteObj()(p2);  
  23.   
  24.     //  
  25.     TestClass* p3 = NULL;  
  26.     NewObjArray()(p3, 5);  
  27.     printf("%p/n", p3);  
  28.     DeleteObjArray()(p3);  
  29. }  

 

 

 Note:测试环境为eclipse+cdt+ubuntu+gcc,注意头文件需要#include <new>,使用#include <stdlib.h>会导致编译不过,因为in-place construtor是C++中的新玩意。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值