author:
- luixiao1223
title: 写了placement new就要写placement delete
问题
Widget *w=new Widget;
- 假如分配内存成功了.
- 但是Widget的构造函数失败了
出现这种情况怎么办?因为用户是拿不到w指针的.所以这个任务只能有运行系统自己负责.
placement new
void* operator new(std::size_t, void* pMemory) throw(); // 你自定义placement new时.可以自定义第二个参数
这个版本的new已经纳入C++标准库了.你只需要 #include <new>
即可.
构造函数失败且你是一个自定义的placement new怎么办?
class Widget {
public:
static void* operator new(std::size_t size,
std::ostream& logStream) throw(std::bad_alloc);
static void operator delete(void *pMemory,
std::size_t size) throw();
};
我们来看看如果客户这样进行调用
Widget *pw = new (std::cerr) Widget;
如果内存分配OK,但是构造函数失败怎么办?运行系统这下是没办法释放内存的.因为它无法找到一个含有placement的delete函数.
class Widget {
public:
static void* operator new(std::size_t size, std::ostream& logStream) throw(std::bad_alloc);
static void operator delete(void *pMemory) throw();//正常形式的delete
static void operator delete(void *pMemory, std::ostream& logStream) throw( );
};
为什么有两个delete?因为一个delete为一般正常形式的delete.它的作用是正常删除的时候用.加入内存分配OK.构造函数也OK.你成功拿到了pw.这个时候你手工删除pw就是调用的正常形式的delete.换句话说,placement
delete是在内存分配OK,但是构造函数不OK的时候才调用.
注意覆盖问题
class Base {
public:
static void* operator new(std::size_t size, std::ostream& logStream) throw(std::bad_alloc);
};
Base *pb = new Base; // Error
Base *pb = new (std::cerr) Base; // OK
class Derived: public Base {
public:
static void* operator new(std::size_t size) throw(std::bad_alloc);
};
Derived *pd = new (std::clog) Derived; // Error
Derived *pd = new Derived; // OK
建议的一种封装继承模式
class StandardNewDeleteForms {
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( )
{
return ::operator new(size, ptr);
}
static void operator delete(void *pMemory, void *ptr) throw() {
return ::operator delete(pMemory, ptr);
}
// No throw
static void* operator new(std::size_t size, const std::nothrow_t& nt) throw()
{
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 delete(void *pMemory, std::ostream&logStream) throw();
};