现在的位置: 首页 > 综合 > 正文

浅析C++中的 new 与 delete 操作

2013年02月27日 ⁄ 综合 ⁄ 共 2364字 ⁄ 字号 评论关闭

new操作符(new operator)与operator new的关系,你想在堆上建立一个对象,应该用new操作符。它既分配内存又为对象调用构造函数。如果你仅仅想分配内存,就应该调用operator new函数;它不会调用构造函数。如果你想定制自己的在堆对象被建立时的内存分配过程,你应该写你自己的operator new函数,然后使用new操作符,new操作符会调用你定制的operator new。如果你想在一块已经获得指针的内存里建立一个对象,应该用placement new。
 我解释一下上面这段,int a=new int(4); 这句中,new会先调用opertor new(size_t,...)这个函数可以重载,且它的第一个参数只能是size_t(unsigned int)类型,它是专门用来分配内存空间的. 然后调用相应的构造函数来生成对象.
 如果重载了operator new(...) ,再使用 new 时,系统会调用重载过的operator new,下面的代码可供测试:
------------------------------------------
void*operator new(size_t a)
{
 cout<<"reload operator new"<<endl;      
 void*pTemp=malloc(a);
 return pTemp;
}
void main()
{
 int *a=new int(7);         //这里,会打印出一行:reload operator new
}
------------------------------------------
placement new 本身不是一个函数,它只是表示从指定位置的内存中去生成一个对象来.下面的代码可作为一个示例:
------------------------------------------
#include <new.h>                       //要引入头文件new.h
void*operator new(size_t a)
{
 cout<<"reload operator new"<<endl;
 void*pTemp=malloc(a);
 return pTemp;
}
void main()
{
 void *pTemp=operator new (1);    //申请一个空间.
 int *a=new(pTemp)int(8);    //把对象产生在这个空间中.
 cout<<*a<<endl;      //实际实用时,这个内存空间应该是比本示例更有意义的地方.
}
由此可见,placement new 的实际是new 的调用有点特别.

下面说一下delete,与new 一样,delete调用时,会先调用析构函数,然后operator delete 来释放空间,但在上面的placement new中,如果内存不是用operator new/new 得到的,比如对象在栈上或另一个堆对象的内部,则不应该调用delete来释放它.

深入一步谈下数组new 与delete:
 string *ps = new string[10];
     在上面这句代码中,被使用的new仍然是new操作符,但是建立数组时new操作符的行为与单个对象建立有少许不同。第一是内存不再用operator new分配,代替以等同的数组分配函数,叫做operator new[](经常被称为array new)。它与operator new一样能被重载。这就允许你控制数组的内存分配,就象你能控制单个对象内存分配一样. 注意,上面虽然有10个string对象,但operator new[]只会被调用一次,这也就是它相对于operator new的优势所在.下面的代码可简单验证:
void*operator new[](size_t a)
{
 cout<<"reload operator new"<<endl;
 void*pTemp=malloc(a);
 return pTemp;
}
void main()
{
 char *p=new char[7];       //只会打印一次reload operator new.
}
-------------------------------------------------
 另外,在释放数组空间时,使用的是:delete []char; 这里,会调用多次析构函数,再调用一次operator delete[],释放全部内存.下面的代码能很好地演示这一点:
--------------------------------------------------
void*operator new[](size_t a)          //重载数组内存分配函数.
{
 cout<<"reload operator new"<<endl;
 void*pTemp=malloc(a);
 return pTemp;
}
void operator delete[](void*pTemp)     //重载数组内存释放函数.
{
 cout<<"reload delete []"<<endl;
 free(pTemp);
}
class mycls        //定义一个类,实现其构造与析构函数.
{
public:
 mycls();
 ~mycls();
};
mycls::mycls()
{
 cout<<"constructor"<<endl;
}
mycls::~mycls()
{
 cout<<"destructor"<<endl;
}

void main()
{
 mycls *p=new mycls[5];      //这里将调用一次operator new[],五次构造函数
 delete []p;     //这里将调用五次析函数,一次operator delete[]

抱歉!评论已关闭.