#include<new>#include<cstdio>#include<Windows.h>usingnamespacestd;char*gPool=NULL;voidmy_new_handler();intmain(){set_new_handler(my_new_handler);gPool=newchar[512*1024*1024];if(gPool!=NULL){printf("Preserve 512MB memory at %x.\n",gPool);}char*p=NULL;for(inti=0;i<4;i++){p=newchar[512*1024*1024];printf("%d * 512M, p = %x\n",i+1,p);Sleep(5000);// 休眠5s}printf("Done.\n");return0;}voidmy_new_handler(){if(gPool!=NULL){printf("try to get more memory...\n");delete[]gPool;// 释放512MB内存空间gPool=NULL;return;}else{printf("I can not help...\n");throwbad_alloc();// 分配失败,抛出异常}return;}
在 Windows 上编译并运行(使用Code::Blocks 13.12 IDE),得到如下输出:
在 C++ 内置 new/delete 中最后的一种是 placement 形式的 new/delete ,即分配的内存地址有用户给定。下面是一个最简单的实例:
123456789101112
#include <cstdio>#include <new>usingnamespacestd;intmain(){charbuffer[100];char*p=new(buffer)char[20];// call placement newprintf("Address of buffer: %x, and p: %x.\n",buffer,p);return0;}// output: Address of buffer: 28feb8, and p: 28feb8.
可以看到 buffer 和 p 的地址是一样的。在大型应用程序中,我们可以充分利用 placement new 的特性,实现自己管理(分配、释放等)本应用的内存空间,基本思路就是: 首先申请一大片内存,然后对每个小的动态内存分配都使用 placement new 的方式进行申请。
2.4 重载 placement new
在 new 操作符中,除了可以使用自定义申请的内存的大小及位置,我们还可以通过重载系统的 new/delete 操作符来加入其它一些附加参数,但仍称之为 placement new 。例如:
12345678910111213141516171819202122232425262728
#include<cstdio>#include<new>usingnamespacestd;#define DEBUG#ifdef DEBUG// 自定义 new 操作符void*operatornew[](unsignedintn,constchar*file,intline){printf("Alloc size: %d at file %s, in line %d\n",n,file,line);return::operatornew(n);}// 自定义 delete 操作符// void operator delete(void *p,const char *file, int line){voidoperatordelete[](void*p,constchar*file,intline){printf("delete at file %s, in line %d\n",file,line);::operatordelete(p);return;}// 宏定义,必须放在重载函数之后#define new new(__FILE__, __LINE__)#define delete delete(__FILE__, __LINE__)#endifintmain(){char*p=newchar[10];//delete p; // delete 的重载还有问题 "error: type 'int' argument given to 'delete', expected pointer"delete[]p;// 直接报语法错误,"error: expected primary-expression before ']' token"return0;}// output: Alloc size: 10 at file D:\Programs\test\main.cpp, in line 22
这在 DEBUG 模式下非常好使。
更新:关于 placement new 的 demo 改为如下代码后就没问题了:
12345678910111213141516171819202122232425
#include<cstdio>#include<new>usingnamespacestd;#define DEBUG#ifdef DEBUG// 自定义 new 操作符void*operatornew[](unsignedintn,constchar*file,intline){printf("Alloc size: %d at file %s, in line %d\n",n,file,line);return::operatornew(n);}// 自定义 delete 操作符voidoperatordelete(void*p,char*file,intline){printf("Delete at file %s, in line %d\n",file,line);::operatordelete(p);return;}// 宏定义,必须放在重载函数之后#define new new(__FILE__, __LINE__)#define delete(ptr) delete(ptr,__FILE__, __LINE__)#endifintmain(){char*p=newchar[10];operatordelete(p);return0;}