Effective C++:条款52 写了placement new也要写placement delete

概述

这个条款的具体内容自己看书去(或者去百度、谷歌,很多人都抄了一遍),我只是对系统会自动调用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 声明\定义位置

operator new与operator delete只能声明/定义与全局作用域或者是声明/定义为类成员,当然类可以声明/定义在某个命名空间。但是operator new与operator delete不能直接声明/定义其他命名空间内。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值