写了placement new也要写placement delete
本文主要内容是对placement new 和 placement delete的介绍,以及在什么情况下使用placement new和placement delete。
对于语句Widget* pw=new Widget;
来说,该语句做了两件事情,第一件事情是申请了内存区域;第二件事情是在该内存区上进行对象的构造,即调用构造函数。我们设想其中一种执行情况,当第一件事情完成,而第二件事情出现异常,那么我们应该怎么去处理,很显然我们需要将这部分内存还原回去,于是如何还原回去成了我们需要解决的问题。
这个时候,客户没有能力去归还内存,因为如果Widget构造函数抛出异常,那么pw尚未被赋值,客户手中的指针还没有指向开辟的内存。释放内存的任务落到了C++运行期系统身上。
class Widget{
public:
static void* operator new(std::size_t size, std::ostream& logStream)//非正常形式的new
throw(std::bad_alloc);
static void operator delete(void* pMemory, std::size_t size)//正常的class专属delete
throw();
……
};
Widget* pw = new(std::cerr) Widget;
我们看到上面的代码,当调用new(std::cerr) Widget
语句时,我们就进入了Widget的自定义new函数中,当构造函数中出现异常的时候,我们可以在构造函数中调用对应的delete函数,实现内存回收。大家如果得到签名式,回收内存就简单了。
我们先来介绍一下placement new 和 placement delete的介绍,术语placement new意味着带有额外参数的new,如void* operator new(std::size_t, void* pMemory) throw();
,placement delete味着带有额外参数的delete。
解决问题的关键变成了如何得到合适的 delete。
根据作者的说明,我们知道
placement delete只有在“伴随placement new调用而触发的构造函数”出现异常时才会被调用。对一个指针施行delete绝不会导致调用placement delete。
这意味对所有placement new我们必须同时提供一个正常的delete和一个placement版本。
class Derived: public Base{
public:
……
static void* operator new(std::size_t size) throw(std::bad_alloc);//重新声明正常形式的new
};
Derived* pd=new (std::clog) Derived;//错误,因为Base的placement new被掩盖了
Derived* pd1=new Derived;//正确
在缺省情况下,C++在global作用域内提供以下形式的operator new:
void* operator(std::size_t) throw(std::bad_alloc);//normal new
void* operator(std::size_t, void*) throw();//placement new
void* operator(std::size_t, const std::nothrow_t&) throw();//nothrow new
class StadardNewDeleteForms{
public:
//normal
static void* operator new(std::size_t size) throw(std::bad_alloc)
{return ::operator new(size);}
static void operator delete(void* pMemory) throw()
{::operator delete(pMemory);}
//placement
static void* operator new(std::size_t size, void* ptr) throw(std::bad_alloc)
{return ::operator new(size, ptr);}
static void operator delete(void* pMemory, void* ptr) throw()
{::operator delete(pMemory, ptr);}
//nothrow
static void* operator new(std::size_t size, const std::nothrow_t& nt) throw(std::bad_alloc)
{return ::operator new(size,nt);}
static void operator delete(void* pMemory,const std::nothrow_t&) throw()
{::operator delete(pMemory);}
};
class Widget: public StandardNewDeleteForms{
public:
//让这些形式可见
using StandardNewDeleteForms::operator new;
using StandardNewDeleteForms::operator delete;
//添加自己定义的
static void* operator new(std::size_t size, std::ostream& logStream) throw(std:;bad_alloc);
static void operator detele(std::size_t size, std::ostream& logStream) throw();
};