如何重载new和delete函数

在嵌入式系统中使用C++的一个常见问题是内存分配,即对new 和 delete 操作符的失控。

  具有讽刺意味的是,问题的根源却是C++对内存的管理非常的容易而且安全。具体地说,当一个对象被消除时,它的析构函数能够安全的释放所分配的内存。

      这当然是个好事情,但是这种使用的简单性使得程序员们过度使用new 和 delete,而不注意在嵌入式C++环境中的因果关系。并且,在嵌入式系统中,由于内存的限制,频繁的动态分配不定大小的内存会引起很大的问题以及堆破碎的风险。

  作为忠告,保守的使用内存分配是嵌入式环境中的第一原则。

  但当你必须要使用new 和delete时,你不得不控制C++中的内存分配。你需要用一个全局的new 和delete来代替系统的内存分配符,并且一个类一个类的重载new 和delete。

  一个防止堆破碎的通用方法是从不同固定大小的内存持中分配不同类型的对象。对每个类重载new 和delete就提供了这样的控制。

  重载全局的new 和delete 操作符

  可以很容易地重载new 和 delete 操作符,如下所示:

void * operator new(size_t size)
{
void *p = malloc(size);
return (p);
}
void operator delete(void *p);
{
free(p);
}

  这段代码可以代替默认的操作符来满足内存分配的请求。出于解释C++的目的,我们也可以直接调用malloc() 和free()。

  也可以对单个类的new 和 delete 操作符重载。这是你能灵活的控制对象的内存分配。

class TestClass {
public:
void * operator new(size_t size);
void operator delete(void *p);
// .. other members here ...
};

void *TestClass::operator new(size_t size)
{
void *p = malloc(size); // Replace this with alternative allocator
return (p);
}
void TestClass::operator delete(void *p)
{
free(p); // Replace this with alternative de-allocator
}

   所有TestClass 对象的内存分配都采用这段代码。更进一步,任何从TestClass 继承的类也都采用这一方式,除非它自己也重载了new 和 delete 操作符。通过重载new 和 delete 操作符的方法,你可以自由地采用不同的分配策略,从不同的内存池中分配不同的类对象。

  为单个的类重载 new[ ] 和 delete[ ]

  必须小心对象数组的分配。你可能希望调用到被你重载过的new 和 delete 操作符,但并不如此。内存的请求被定向到全局的new[ ]和delete[ ] 操作符,而这些内存来自于系统堆。

  C++将对象数组的内存分配作为一个单独的操作,而不同于单个对象的内存分配。为了改变这种方式,你同样需要重载new[ ] 和 delete[ ]操作符。

#include <iostream>

#include <cstdlib>

#include < new >

using  namespace std;

class  MyClass  {

   int  x, y;

public :

   MyClass () {

      x = y =  0 ;

   }
  
   MyClass ( int  lg,  int  lt ) {

     x = lg;

     y = lt;
   }

   void  show () {

     cout << x <<  " " ;

     cout << y << endl;

   }

   void  *operator  new ( size_t size ) ;

   void  operator  delete ( void  *p ) ;

   void  *operator  new []( size_t size ) ;

   void  operator  delete []( void  *p ) ;
} ;

// overloaded new operator
void  *MyClass::operator  new ( size_t size )
{
   void  *p;

   cout <<  "In overloaded new./n" ;
  
   p =  malloc ( size ) ;
  
   if ( !p ) {
  
     bad_alloc ba;
  
     throw  ba;
   }
   return  p;
}

// delete operator overloaded
void  MyClass::operator  delete ( void  *p )
{
  
   cout <<  "In overloaded delete./n" ;
  
   free ( p ) ;
}

// new operator overloaded for arrays.
void  *MyClass::operator  new []( size_t size )
{
   void  *p;

   cout <<  "Using overload new[]./n" ;
  
   p =  malloc ( size ) ;
  
   if !p  ) {
  
     bad_alloc ba;
  
     throw  ba;
   }
  
   return  p;
}

// delete operator overloaded for arrays.
void  MyClass::operator  delete []( void  *p )
{
   cout <<  "Freeing array using overloaded delete[]/n" ;
  
   free ( p ) ;
}

int  main ()
{
   MyClass *objectPointer1, *objectPointer2;

   int  i;

   try  {
  
     objectPointer1 =  new  MyClass  ( 10 20 )
  
   catch  ( bad_alloc xa ) {
  
     cout <<  "Allocation error for objectPointer1./n" ;
  
     return  1 ;;
   }

   try  {
  
  
     objectPointer2 =  new  MyClass  [ 10 ] ;                // allocate an array
  
   catch  ( bad_alloc xa ) {
  
     cout <<  "Allocation error for objectPointer2./n" ;
  
     return  1 ;;
   }

   objectPointer1->show () ;
  
   for i =  0 ; i <  10 ; i++ )
     objectPointer2 [ i ] .show () ;

   delete  objectPointer1;                              // free an object
   delete  []  objectPointer2;                           // free an array

   return  0 ;
}

 

  但是注意:对于多数C++的实现,new[]操作符中的个数参数是数组的大小加上额外的存储对象数目的一些字节。在你的内存分配机制重要考虑的这一点。你应该尽量避免分配对象数组,从而使你的内存分配策略简单。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值