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(); };
相关文章推荐
- 使用VS2010在项目中编写C++头文现出"PCH 警告:标头停止点不能位于宏或#if块中"
- 《深入应用C++11:代码优化与工程级应用》
- c语言结构体用法
- C++ 关于滚动条的滚动问题
- 用C/C++开发基于VLC SDK的视频播放器
- 关于C语言中函数调用和参数传递机制的探讨 (转)
- C/C++中赋值语句的返回值问题
- C++实现DES加密解密
- Effective C++ 条款51
- 【转】[C++]实现委托模型
- 2015年oj刷题:实现复数类中的加运算符重载【C++运算符重载】
- c++基础学习(05PM)
- C++学习笔记(二)STL简介(一)
- C++利用IO流对浮点数进行格式化控制输出
- C++头文件预编译与命名空间使用方法
- 【学习笔记】【C语言】进制
- ID3算法 决策树 C++实现
- C++标准库学习笔记(Shared Pointer)-3
- eclipse安装C/C++插件cdt
- Effective C++条款05解读: 了解C++默默编写并调用哪些函数