概述
这个条款的具体内容自己看书去(或者去百度、谷歌,很多人都抄了一遍),我只是对系统会自动调用placement new对应的placement delete 感兴趣,写了下面的代码,下面的代码没有实际意义,只是为了体现系统自动调用相应的placement delete。
什么是placement 版本的new与delete
所谓placement new与placement delete就是带附加参数的 operator new 与operator delete,不带附加参数的 operator new 与operator delete如下:
void* operator new(std::size_t size)throw(std::bad_alloc);
void operator delete(void* pointer) throw();
那么带附加参数的版本也就很显然,如:
void* operator new(std::size_t size,int p)throw(std::bad_alloc);
void operator delete(void* pointer,int p)throw();
标准库给我们定义了一对placement new,接受一个对象被构建的地址形式如下:void* operator new(std::size_t size,void*pointer)throw(std::bad_alloc);
当然要想调用这些placement版本的new与delete,就需要给出相应的附件参数,如:
new (1) int(4) ; ==> void* operator new(std::size_t size,int p)throw(std::bad_alloc);
new与delete执行过程 与 异常
new分两步,先是operator new, 然后是构造函数,想必大家都很清楚。这两步都可能抛出异常:
如果是operator new 部分不能成功分配内存,那么在handler不为NULL时,会掉应相应的handler(这个可以通过 std::set_new_handler实现)处理,这可以参见条款51。
如果是operator new 成功分配内存,未抛出异常,而在内存上构建对象,调用构造函数出现异常的时候,这时系统会自动调用和与operator new 附加参数一致的operator delete(可以都是没有附加参数)来清理内存,(如果没有附加参数一致的operator delete 那么系统不会调用任何operator delete),然后由上层来处理构造函数的异常。
代码及解释
#include <iostream>
class base{
public:
base(){
std::cout<<"base constructor"<<std::endl;
int a=1;
throw a;
}
};
class test{
public:
~test(){
std::cout<<"deconstructor in test"<<std::endl;
}
};
void * operator new (size_t size,int which )throw(std::bad_alloc){
std::cout<<"my operator new : int placement"<<std::endl;
return ::operator new(size);
}
void operator delete (void *p,int which )throw(){
std::cout<<"my operator delete : int placement "<<std::endl;
}
void operator delete (void *p )throw(){
std::cout<<"my operator delete : no additional params"<<std::endl;
}
void myHandler(){
static int times =1;
if(times>=3)
throw std::bad_alloc();
std::cout<<"new failed "<<std::endl;
++times;
}
int main(int argc,char** argv){
std::set_new_handler(myHandler);
try{
test t;
base*b=new (1)base;
}catch (...){
std::cout<<"catch exception"<<std::endl;
//operator delete (t,1);//can call it directly
}
std::cout<<"end"<<std::endl;
}
运行结果,注意placement delete调用时机
my operator new : int placement
base constructor
my operator delete : int placement
deconstructor in test
catch exception
end
operator new [] 与operator delete[]同理
注意operator new 与operaotr delete 为类成员和普通函数时区别
非类成员函数时:
void* operator new(std::size_t size)throw(std::bad_alloc); 与void operator delete(void* pointer) throw();是对应的
类成员函数时:
void* operator new(std::size_t size)throw(std::bad_alloc); 与void operator delete(void* pointer) throw(); 或void operator delete(void* pointer,std::size_t size) throw(); 是对应的,且优先是前者。
operator new 与operaotr delete 声明\定义位置