条款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 };
时间: 2024-08-11 05:44:33

条款52:谢了placement new 也就同时应该写一个placement delete的相关文章

Effective C++ 条款 52:写了placement new也要写placement delete

(一) 当我们写下了下面这个语句: Widget* pw = new Widget; 这个时候,共有两个函数被调用:一个分配内存的operator new,另外一个是Widget的default构造函数. 假设第一个调用成功,第二个却抛出异常.步骤一所分配内存必须取消并恢复旧观,否则会造成内存泄漏.这时,客户没能力归还内存,因为Widget构造函数抛出异常,pw尚未被赋值,客户手上也就没有指针指向该被归还的内存. 这个时候,取消步骤一,并恢复旧观的责任就落到C++运行系统身上. 运行期系统会高兴

Effective C++ 条款52 写了placement new也要写placment delete

1. placement new和place ment delete指的是正常的operator new和operator delete的重载版本,所谓的正常的operator new和delete,指的是拥有以下正常签名式的版本: void* operator new(std::size_t) throw(std::bad_alloc); void operator delete(void*) throw(); //global作用域中的正常签名式 void operator delete(v

Item 52:写了placement new就要写placement delete

Item 52: Write placement delete if you write placement new "placement new"通常是专指指定了位置的new(std::size_t size, void *mem),用于vector申请capacity剩余的可用内存. 但广义的"placement new"指的是拥有额外参数的operator new. new和delete是要成对的,因为当构造函数抛出异常时用户无法得到对象指针,因而delete

Effective C++ 条款52

写了placement new也要写placement delete 本文主要内容是对placement new 和 placement delete的介绍,以及在什么情况下使用placement new和placement delete. 对于语句Widget* pw=new Widget;来说,该语句做了两件事情,第一件事情是申请了内存区域:第二件事情是在该内存区上进行对象的构造,即调用构造函数.我们设想其中一种执行情况,当第一件事情完成,而第二件事情出现异常,那么我们应该怎么去处理,很显然

Effective C++ 的55个条款

看完Effective C++才觉得平时程序设计时需要注意的一些问题,有一定的收获,不过因为没什么项目实践, 并未很深入了解具体情况如何,还需后继实践~ 列举一下55个条款: 1. 视C++为一个语言联邦. 2. 尽量以const, enum ,inline 替换#define a)  对于单纯常量,最好以const 对象或 enum 替换 #define b)  对于形似函数的宏,最好改用inline 函数替换 #define 3. 尽可能使用const a)  将某些东西声明为const可帮

Effective C++ 55条款及应该记住的事项

1. 让自己习惯C++ 01. 视C++为一个语言联邦 请记住:  C++高效编程守则视状况而变化,取决于你使用C++的哪一部分 02. 尽量以const,enum,inline,替换#define 请记住:  对于单纯变量,最好以const对象或enums替换#defines  对于形似函数的宏(macros),最好改用inline函数替换#defines 03. 尽可能使用const 请记住:  将某些东西声明为const可帮助编译器侦测出错误用法.const可被施加于任何作用域内的

Effective C++ 55个条款

Effective C++ 55个条款 让自己习惯C++ 视C++为一个语言联邦 C++高效编程守则视状况而变化,取决于你使用C++的哪一部分. 尽量以const,enums,inline替换#define 对于单纯常量,最好以const对象或enums替换#defines: 对于形似函数的宏(macros),最好改用inline函数替换#defines. 尽可能使用const 将某些东西声明为const可帮助编译器侦测出错误用法.const可被施加于任何作用域内的对象.函数参数.函数返回类型.

《effective c++》读书笔记4

条款41:了解隐式接口和编译期多态 n  classes和templates都支持接口和多态 n  对classes而言接口是显式的,以函数签名为中心,多态则是通过虚函数发生于运行期. n  对templates参数而言,接口是隐式的,奠基于有效表达式,多态则是通过template具现化和函数重载解析发生于编译器. 条款42:了解typename的双重意义 n  声明模板参数,前缀关键字class和typename可互换. n  请使用关键字typename标识嵌套从属类型名称,但不得在基类或者

[Effective C++]定制new和delete

本篇的两个主角是分配例程和归还例程(allocation and deallocation routines,也就是operator new和operator delete),配角是new_handler,这是当operator new无法满足客户的内存需求时所调用的函数. STL容器所使用的heap内存是由容器所拥有的分配器对象(allocator objects)管理,不是被new和delete直接管理. 条款49:了解new-handler的行为(Understand the behavi