当咱们建立一个new表达式时,会发生两件事。首先使用operator new()分配内存,而后调用构造函数。在delete表达式里,调用了析构函数,而后使用operator delete()释放内存。咱们没法控制构造函数与析构函数的调用,可是能够改变内存分配函数operator new()和operator delete().ios
在使用系统内置的new和delete的内存分配系统是为了通用的目的而设计的,可是在特殊的情形下,它并不能知足需求。有时候咱们为了改善程序的效率,咱们会重载operator new和operator delete. 也许要建立和销毁一个特定的类的很是多的对象以致于这个运算变成了速度的瓶颈。因此此时咱们会选择重载new和delete.函数
重载new和delete的理由还有防止内存碎片:分配大小不一样的内存可能会在堆上产生不少碎片,以致于很快用完内存。虽然内存可能还有,但因为都是碎片,也就找不到足够大的内存知足需求。经过为特定类建立本身的内存分配器,能够确保这种状况不会发生。spa
注意:咱们虽然重载了new和delete,其实咱们只是改变了内存分配和释放的部分,而内存构造函数和析构函数调用的部分没有改变。设计
当operator new()找不到足够大的内存块来安排对象时,将对有一个特殊的函数被调用,这个函数是new-handler。new-handler的默认的动做是产生一个异常(exception)指针
1 #include<iostream> 2 #include<cstdlib> 3 #include<new> 4 using namespace std; 5 int count=0; 6 7 void out_of_memory(){ 8 cerr<<"memory exhausted after"<<count<<"allocations!"<<endl; 9 exit(1); 10 11 } 12 13 int main(){ 14 set_new_handler(out_of_memory); 15 while(1){ 16 count++; 17 new int[1000]; 18 } 19 20 }
上面的代码就是在内存耗尽时,new operator操做符调用new-handler函数out_of_memory。new-handler函数必须没有参数,返回值必须为void。那么咱们在重载operator new时,也可改变用完内存时的行为,一种方法即便经过new-handler函数实现。code
重载new和delete与重载别的运算符同样,能够经过全局函数重载,也能够经过对特定的类的成员函数重载。固然经过全局函数重载new和delete是很是极端的作法,不建议这样作,虽然语法上是容许的。由于经过全局函数重载new和delete,那么编译器默认的版本就不能再使用了。对象
重载new和delete语法,首先重载的new必须有一个size_t参数,这个参数是编译器产生并传递给咱们,它是要分配内存的对象的长度。必须返回一个执行那个等于或者大于这个长度的对象指针,若是没有找到存储单元,则返回一个0.若是真没有找到存储单元,不能仅仅返回0,也许还应该作一些诸如调用new-handler或者产生一个void*的异常信息。 重载的new operator()要返回一个void*指针。operator delete()的参数也是一个void*指针,参数之因此是一个void*指针,是由于它是在调用析构函数后获得的指针,析构函数从存储单元里移除对象。opreator delete的返回类型是void。blog
1 #include<cstdio> 2 #include<cstdlib> 3 using namespace std; 4 5 void* operator new(size_t sz){//重载的new 6 printf("operator new: %d\n",sz); 7 void* m= malloc(sz); 8 if (!m) 9 puts("out of memory"); 10 return m; 11 } 12 13 void operator delete(void* m){//重载的delete 14 puts("operaor delete"); 15 free(m); 16 } 17 18 class S{ 19 int i[100]; 20 public: 21 S(){ puts("S::S()"); } 22 ~S(){ puts("S::~S()"); } 23 24 }; 25 26 int main(){ 27 puts("creating & destorying an int"); 28 int* p = new int(42); 29 delete p; 30 puts("creating & destorying an s"); 31 S* s = new S; 32 delete s; 33 puts("creating & destorying an S[3]"); 34 S* sa = new S[3]; 35 delete[] sa; 36 return 0; 37 }