您的位置:首页 > 编程语言 > C语言/C++

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

2006-07-28 21:29 489 查看
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[]
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: