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

《Effective C++第三版》读书笔记——定制new和delete

2015-05-26 07:29 519 查看
8 定制new和delete

~~~~~~~~~~~~~~~~~~

8.1 了解new-handler的行为

==========================

1. 当opeartor new无法满足某一内存分配需求时,它会抛出异常.在这之前,它会先调用一个客户指定的错误处理函数,所谓的new-handler

2. 用户必须通过调用set_new_handler来设置new-handler函数,set_new_handler的参数是指向new-handler函数的指针

3. new-handler函数应该没有参数,也不返回任何东西(void)

4. 当operator new无法满足内存申请时,它会 *不断* 调用new-handler函数,直到找到足够内存!

5. 一个设计良好的new-handler函数必须做以下事情中的一个或几个

* 让更多内存可被使用

一个做法是,程序一开始执行就分配一大块内存,然后当new-handler第一次调用,将它们释放给程序使用

* 安装另一个new-handler

(否则会不断调用这个new-handler,进入死循环)

* 卸除new-handler

也就是将null指针传给set_new_handler,这样operator new会在内存分配不成功时抛出异常

* 抛出bad_alloc

* 退出程序

通常调用abor或exit

6. 使用new (std::nothrow),如果分配内存失败,不会抛异常,而是返回NULL值,nothrow定义于<new>

8.2 写new和delete时需固守常规

==============================

1. operator new应该内含一个无穷循环,并在其中尝试分配内存,如果无法满足内存需求,就调用new-handler.

它也应该有能力处理0bytes申请.

由于类中的operator new成员函数会被子类继承,因此class专属版本则还需要处理"比正确大小更大的错误申请"

//non-member operator new伪代码
void* operator new(std::size_t size)throw(std::bad_alloc)
{
using namespace std;
if(size == 0){
size = 1;    //处理0-bye申请,将它视为1-bye申请,因为C++不允许大小为0的对象
}
while(true){
尝试分配size bytes;
if(分配成功){return 指向内存的指针;}
//分配失败,找出目前的new-hander函数并调用
new_handler globalHandler = set_new_handler(NULL);
set_new_handler(globalHandler);
if(globalHandler){
(*globalHandler)();
}else{
throw std::bad_alloc();
}
}
}


2. operator new[]唯一需要做的一件事就是分配一块未加工内存.

3. operator delete应该在收到null指针时,不做任何事.class专属版本则还应该处理"比正确大小更大的错误申请"

8.3 写了placement new也要写placement delete

============================================

1. 如果operator new接受的参数除了一定会有的那个size_t之外,还有其他参数,这便是个所谓的placement new.

2. 相应的placement delete指"参数个数和类型都与operator new相同的"operator delete

3. 运行期,若replacement new抛出异常,则系统会去找与placement new相对应的placement delete版本,若找不到则什么也不做.

但是placement delete只有在"伴随placement new调用而触发的构造函数"出现异常时才会被编译器自动调用.对一个指针显式调用delete不会导致调用placement delete.

4. 缺省情况下,C++在global作用域提供三种形式的operatornew

* void* operator new(std::size_t)throw(std::bad_alloc);  //normal new
* void* operator new(std::size_t,void*) throw();         //placement new
* void* operator new(std::size_t,const std::nothrow_t&)throw()//nothrow new


5. 当声明了专有类的new和delete之后,请注意,它会遮掩std的标准new和delete.
本文出自 “暗日” 博客,请务必保留此出处http://darksun.blog.51cto.com/3874064/1148742
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: