条款52:谢了placement new 也就同时应该写一个placement delete

如果operator new接收到的参数除了size_t之外还有其他的话,那么这个operator new实际上就是一个placement new,所以考虑下下面这样的情况:

一个可以用来记录信息的placement new:
1 class Widget{
2 public:
3     ...
4     static void * operator new(std::size_t size, std::ostream & logStream = std::cout) 
5         throw(std::bad_alloc);
6     static void * operator delete(void * pMem, std::size_t size) throw();
7     ...
8 };

那么当我们新建一个Widget的时候:

1 Widget * wgt = new (std::cerr)Widget;
这时,如果在new的时候成功但是在构造Widget的时候失败,那么系统寻找不到相应的delete可以将分配的raw内存释放掉,这样就会引起内存泄漏了。
 
所以在提供placement new 的时候一定要提供相应的placement delete,这样就不会发生内存泄漏。
placement delete如下所示:
1 static void operator delete(void * pMem, std::ostream& logStream);

完成所有的要点的简单的形式是,建立一个base class, 内含有所有正常形式的new以及delete.完成所有的要点的简单的形式是,建立一个base class, 内含有所有正常形式的new以及delete.完成所有的要点的简单的形式是,建立一个base class, 内含有所有正常形式的new以及delete.

 1 class StandardNewDeleteForms{
 2 public:
 3     //normal new / delete
 4     static void * operator new(std::size_t size) throw(std::bad_alloc)
 5     {
 6         return ::operator new(size);    //这里使用的是全局的new
 7     }
 8     static void operator delete(void * pMem) throw()
 9     {
10         return ::operator delete(pMem);
11     }
12     //placement new / delete
13     static void * operator new(std::size_t size, void * ptr) throw()
14     {
15         return ::operator new(size, ptr);
16     }
17     static void operator delete(void * pMem, void * ptr)throw()
18     {
19         return ::operator delete(pMem, ptr);
20     }
21     //nothrow new/delete
22     static void * operator new(std::size_t size, const std::nothrow_t & nt) throw()
23     { return ::operator new(size, nt);}
24     static void operator delete(void * pMem, const std::nothrow_t & nt) throw()
25     { return ::operator delete(pMem, nt)}
26 };

然后既可以使用继承以及using声明获得想要的new以及delete:

1 class Widget : public StandardNewDeleteForms{
2 public:
3     using StandardNewDeleteForms::operator new;
4     using StandardNewDeleteForms::operator delete;    //将他们引入作用域,以免全局的new以及delete被遮盖的掉。
5     static void * operator new(std::size_t size,
6                         std::ostream & logStream) throw(std::bad_alloc);
7     static void * operator delete(void * pMem, 
8                         std::ostream & logStream) throw();
9 };

 

posted @ 2015-10-18 17:40  eversliver  阅读(321)  评论(0编辑  收藏  举报