您的位置:首页 > 编程语言 > C语言/C++

Effective C++ 条款52

2015-06-17 09:53 369 查看

写了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();
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: