详解C++中new运算符和delete运算符的使用

2020-01-06 14:37:54王振洲

delete 运算符
可使用 delete 运算符释放使用 new 运算符动态分配的内存。delete 运算符调用 operator delete函数,该函数将内存释放回可用池。使用 delete 运算符也会导致调用类析构函数(如果有)。
存在全局和类范围的 operator delete函数。只能为给定类定义一个 operator delete函数;如果定义了该函数,它会隐藏全局 operator delete函数。始终为所有类型的数组调用全局 operator delete函数。
全局 operator delete函数(如果已声明)采用 void * 类型的单个参数,该参数包含指向要释放的对象的指针。返回类型是 void(operator delete 无法返回值)。类成员 operator delete 函数有两种形式:


void operator delete( void * );
void operator delete( void *, size_t );

给定类中只存在前面两个变量中的一个。第一个形式按照为全局 operator delete 描述的那样运行。第二个形式采用两个参数,第一个是指向要释放的内存块的指针,第二个是要释放的字节的数量。当基类中的 operator delete 函数用于删除派生类的对象时,第二个形式特别有用。
operator delete 函数是静态的;因此它不能是虚函数。 operator delete 函数服从访问控制,如成员访问控制中所述。
以下示例显示旨在记录内存的分配和释放的用户定义的 operator new 和 operator delete 函数:


// spec1_the_operator_delete_function1.cpp
// compile with: /EHsc
// arguments: 3
#include <iostream>
using namespace std;

int fLogMemory = 0;  // Perform logging (0=no; nonzero=yes)?
int cBlocksAllocated = 0; // Count of blocks allocated.

// User-defined operator new.
void *operator new( size_t stAllocateBlock ) {
 static int fInOpNew = 0; // Guard flag.

 if ( fLogMemory && !fInOpNew ) {
  fInOpNew = 1;
  clog << "Memory block " << ++cBlocksAllocated
   << " allocated for " << stAllocateBlock
   << " bytesn";
  fInOpNew = 0;
 }
 return malloc( stAllocateBlock );
}

// User-defined operator delete.
void operator delete( void *pvMem ) {
 static int fInOpDelete = 0; // Guard flag.
 if ( fLogMemory && !fInOpDelete ) {
  fInOpDelete = 1;
  clog << "Memory block " << cBlocksAllocated--
   << " deallocatedn";
  fInOpDelete = 0;
 }

 free( pvMem );
}

int main( int argc, char *argv[] ) {
 fLogMemory = 1; // Turn logging on
 if( argc > 1 )
  for( int i = 0; i < atoi( argv[1] ); ++i ) {
   char *pMem = new char[10];
   delete[] pMem;
  }
 fLogMemory = 0; // Turn logging off.
 return cBlocksAllocated;
}

前面的代码可用于检测“内存溢出”,即在自由储存中分配但从未释放过的内存。若要执行此检测,则应重新定义全局 new 和 delete 运算符以计算内存的分配和释放。