new和delete是语言关键字,它分为两个部分
new:operator new(申请空间)------构造函数初始化
delete:析构函数析构---------------operator delete(释放空间)
而在operator new 和operator delete中又分为global new和placement new以及global delete和placement delete
一般所谓的重载new和delete只是重载operator new和operator delete
以下分析global new和global delete
void *operator new(unsigned int a)//(1)
{
printf("new/n");
return malloc(a);
};
void *operator new(unsigned int a, bool)//(2)
{
printf("bool new/n");
return operator new(a);
};
void *operator new[](unsigned int a)//(3)
{
printf("new array/n");
return malloc(a);
};
void operator delete(void *memP)//(4)
{
printf("delete/n");
free(memP);
};
void operator delete(void *memP, bool)//(5)
{
printf("bool delete/n");
operator delete(memP);
};
void operator delete[](void *memP)//(6)
{
printf("delete array/n");
free(memP);
};
void main()
{
int* pa1 = new(0) int(0);//call 2
delete pa1;//call 4
int* pa2 = new int;//call 1
delete pa2;//call 4
int* pa3 = new int;//call 1
operator delete(pa3, 0);//call 5
int* pa4 = new(0) int;//call 2
delete(0) pa4;//编译错误,测试平台为VC6.0(我觉得不应该会有问题,应该是编译器的问题,暂时还没有在其它编译器下尝试过)
int* paArray = new int[10];//call 3
delete[] paArray;//call 6
}
int* pa1 = new(0) int(0);//call 2 这个就是典型的先申请空间然后够早初始化
以下placement new和placement delete
#include <stdlib.h>
#include<stdio.h>
class AAA
{
public:
AAA(){printf("AAA constructor!!!/n");}
static void * operator new(unsigned int size){printf("AAA:new/n");return malloc(size);}//(1)
static void operator delete(void *memP){printf("AAA:delete/n");free(memP);}//(2)
static void * operator new(unsigned int size, bool){printf("AAA:bool new/n"); return malloc(size);}//(3)
static void operator delete(void *memP, bool){printf("AAA:bool delete/n");free(memP);}//(4)
static void * operator new[](unsigned int size){printf("AAA:new array/n");return malloc(size);}//(5)
static void operator delete[](void *memP){printf("AAA:delete array/n");free(memP);}//(6)
~AAA(){printf("AAA destructor!!!/n");}
};
class BBB:public AAA
{
public:
BBB(){printf("BBB constructor!!!/n");}
~BBB(){printf("BBB destructor!!!/n");}
};
class CCC
{
public:
CCC(){printf("CCC constructor!!!/n");}
static void * operator new(unsigned int size){printf("CCC:new/n");return malloc(size);}//(7)
static void operator delete(void *memP){printf("CCC:delete/n");free(memP);}//(8)
static void * operator new(unsigned int size, bool){printf("CCC:bool new/n");return malloc(size);}//(9)
static void operator delete(void *memP, bool){printf("CCC:bool delete/n");free(memP);}//(10)
~CCC(){printf("CCC destructor!!!/n");}
};
void main()
{
AAA* aaa1P = new AAA;//call 1
delete aaa1P;//call 2
AAA* aaa2P = new(true) AAA;//call 3
delete(true) aaa2P;//编译不过
AAA::operator delete(aaa2P, true);//call 4
AAA* aaa3P = new AAA[10];//call 5
delete[] aaa3P;//call 6
AAA* aaa4P = new AAA[10];//call 5
AAA::operator delete[](aaa4P);//call 6 vc6.0下会出现执行错误
BBB* bbb1P = new BBB;//call 1
delete bbb1P;//call 2
BBB* bbb2P = new(true) BBB;//call 3
BBB::operator delete(bbb2P, true);//call 4
CCC* ccc1P = new CCC;//call 7
delete ccc1P;//call 8
CCC* ccc2P = new(true) CCC;//call 9
CCC::operator delete(ccc2P, true);//call 10
}
注:
1. AAA* aaa3P = new AAA[10];//call 5
先会生成10个AAA类对象的空间,然后在每个AAA空间中执行构造函数,而不是每new一个AAA对象空间,再执行AAA的构造函数
delete[] aaa3P;//call 6
先执行10个AAA对象的析构函数,然后释放10个AAA对象的空间
AAA* aaa4P = new AAA[10];//call 5
AAA::operator delete(aaa4P);//call 6
这样调用仅仅是释放空间,而不会调用析构函数,这样比较危险,一般不建议这样做
BBB类中虽然没有重载new和delete,但是它继承了AAA的new和delete,这样做会比较危险(可能造成内存泄漏,下回分析)
2.为什么placement new和delete是static?
以new为例,operator new申请空间之前,构造函数还未执行,也就没有this指针,所以它必须是static,属于这个类而不是属于某个对象
globa和placement混合用
#include <stdlib.h>
#include<stdio.h>
class AAA
{
public:
AAA(){printf("AAA constructor!!!/n");}
static void * operator new(unsigned int size){printf("AAA:new/n");return malloc(size);}
static void operator delete(void *memP){printf("AAA:delete/n");free(memP);}
static void * operator new[](unsigned int size){printf("AAA:new array/n");return malloc(size);}
static void operator delete[](void *memP){printf("AAA:delete array/n");free(memP);}
static void * operator new(unsigned int size, bool){printf("AAA:bool new/n"); return malloc(size);}
static void operator delete(void *memP, bool){printf("AAA:bool delete/n");free(memP);}
~AAA(){printf("AAA destructor!!!/n");}
};
void *operator new(unsigned int a)
{
printf("new/n");
return malloc(a);
};
void *operator new[](unsigned int a)
{
printf("new array/n");
return malloc(a);
};
void *operator new(unsigned int a, bool)
{
printf("bool new/n");
return operator new(a);
};
void operator delete(void *memP)
{
printf("delete/n");
free(memP);
};
void operator delete[](void *memP)
{
printf("delete array/n");
free(memP);
};
void operator delete(void *memP, bool)
{
printf("bool delete/n");
operator delete(memP);
};
void main()
{
int* pa = new(0) int(0);
delete pa;
int* paArray = new int[10];
delete[] paArray;
AAA* pAAA = new AAA;
delete pAAA;
AAA* pAAAArray = new AAA[10];//执行AAA::operator new[]
如果AAA中没有重载new,则执行的是global new
AAA::operator delete[](pAAAArray);//执行AAA::operator delete[]执行错误
// delete[] pAAAArray;///执行AAA::operator delete[]和相应的析构函数
如果AAA中没有重载delete,则执行的是global delete
}
终上所述:
1.重载new第一个参数必须是unsigned int,返回值必须是void*;
重载delete第一个参数必须是void*,返回值必须为void
2.在vc6.0下,除了显式调用除operator delete(void*)形式以外的operator delete函数,不能殷实调用delete
3.从第三个例子可以看出来,其实global和placement都是一样的,placement形式是static类型,其实也是一个全局的函数,只是它受保护,不能随便被外部调用到。