【effective c++】定制new和delete
条款49: 了解new-handler的行为
operator new 和 operator delete只适合用来分配单一对象。array所用的内存由operator new[]分配出来,并由operator delete[] 释放。
1、了解new-handler的行为
当operator new无法满足某一内存分配需求时,它会先调用指定的错误处理函数(new-handler),然后抛出异常。可通过set_new_handler函数来设置new-handler。
namespace std {
typedef void (*new_handler)();
new_handler set_new_handler(new_handler p) throw();
}
new_handler是个typedef,定义出一个指针指向函数,该函数没有参数也不返回任何东西。
为当前class提供专属new-handler,只需为它提供自己的set_new_handler和operator new(分配内存)即可。
class Widget {
public:
static std::new_handler set_new_handler(std::new_handler p) throw();
static void* operator new(std::size_t size) throw(std::bad_alloc);
private:
static std::new_handler currentHandler;
};
std::new_handler Widget::currentHandler = ;
// 注意此处要返回之前使用的new_handler
std::new_handler Widget::set_new_handler(std::new_handler p) throw() {
std::new_handler oldHandler = currentHandler;
currentHandler = p;
return oldHandler;
}
void* Widget::operator new(std::size_t size) throw(std::bad_alloc) {
NewHandlerHolder h(std::set_new_handler(currentHandler));
return ::operator new(size);
}
// 为确保原本的new-handler能够被重新安装回去, 运用资源管理对象
class NewHandlerHolder {
public:
explicit NewHandlerHolder(std::new_handler nh): handler(nh){}
~NewHandlerHolder(){
std::set_new_handler(handler);
}
private:
std::new_handler handler;
// 防止copy
NewHandlerHolder(const NewHandlerHolder&);
NewHandlerHolder& operator=(const NewHandlerHolder&);
};
使用nothrow new只能保证operator new不抛出异常,若分配失败则返回NULL,不保证new (std::nothrow) Widget这样的表达式绝不导致异常,因为Widget构造函数中可能继续new内存出现异常
Widget *p = new (std::nothrow) Widget;
条款50:了解new和delete的合理替换时机 <pass>
条款51:编写new和delete时需固守常规
1、operator new应该内含一个无穷循环, 并在其中尝试分配内存,如果它无法满足内存需求,就该调用new-handler.
2、operator delete应该在收到null指针时不做任何事
class Base {
public:
static void* operator new(std::size_t size) throw(std::bad_alloc) ;
static void operator delete(void *rawMemory, std::size_t size) throw();
};
/*
operator new成员函数会被derived class继承,而定制内存管理器的一个常见理由是为某特定class的对象
分配行为提供最优化,即针对Base类设计的operator new其行为可能只为大小刚好为sizeof(Base)的对象而设计
*/
void* Base::operator new(std::size_t size) throw(std::bad_alloc) {
if (size != sizeof(Base)) {
return ::operator new(size);
}
// 专为Base类定制的行为
// ...
}
void Base::operator delete(void *rawMemory, std::size_t size) throw() {
if (rawMemory == ) {
return;
}
// 与上述::operator new对应
if (size != sizeof(Base)) {
::operator delete(rawMemory);
return;
}
// 释放rawMemory所指的内存
return;
}
条款52:写了placement new也要写placement delete
placement new: 多了pMemory参数
void* operator new(std::size_t size, void* pMemory) throw();
如果一个带额外参数的operator new 没有带相同额外参数的对应版operator delete,那么当new的内存分配动作需要取消并恢复原样时就没有任何operator delete会被调用,导致内存泄漏。
placement delete只有在伴随placement new调用而触发的构造函数出现异常时才会被调用,delete某指针时不会导致调用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();
static void operator delete(void *pMemory, std::ostream &logStream) throw();
};
// 若引发Widget构造函数抛出异常,会自动调用placement delete
Widget *pw = new (std::cerr) Widget;
// 调用正常的operator delete
delete pw;
缺省情况下c++在global作用域内提供以下形式的operator new:
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();
如果在class内声明任何operator new,会隐藏上述这些标准形式。为避免出现这种情况,可以建立一个Base class,内含所有正常形式的new和delete,凡是想以自定义形式扩充标准形式的客户,可利用继承机制及using 声明式取得标准形式。
【effective c++】定制new和delete的更多相关文章
- Effective C++ —— 定制new和delete(八)
STL容器所使用的heap内存是由容器所拥有的分配器对象管理,不是被new和delete直接管理.本章并不讨论STL分配器. 条款49 : 了解new-handler的行为 当operator new ...
- 高效C++:定制new和delete
内存的申请和释放,C++从语言级别提供了new和delete关键字,因此需要了解和熟悉其中的过程. 了解new-handler的行为 set_new_handler可以指定一个函数,当申请内存失败时调 ...
- Effective C++: 08定制new和delete
49:了解new-handler的行为 当operator new无法满足某一内存分配需求时,它会抛出异常(以前会返回一个null).在抛出异常之前,它会调用一个客户指定的错误处理函数,也就是所谓的n ...
- 《Effective C++》定制new和delete:条款49-条款52
条款49:了解new-handler的行为 当operator new无法分配出内存会抛出异常std::bad_alloc 抛出异常前会反复调用用户自定义的new-handler函数直至成功分配内存 ...
- 八、定制new和delete
条款49:了解new-handler的行为 new异常会发生什么事? 在旧式的编译器中,operator new分配内存失败的时候,会返回一个null指针.而现在则是会抛出一个异常. 而在抛出这个异常 ...
- 《Effective C++》读书摘要
http://www.cnblogs.com/fanzhidongyzby/archive/2012/11/18/2775603.html 1.让自己习惯C++ 条款01:视C++为一个语言联邦 条款 ...
- 《Effective C++》 阅读小结 (笔记)
A person who is virtuous is also courteous. "有德者必知礼" 书本介绍:<Effective C++:改善程序与设计的55个具体做 ...
- C++ delete 和 delete []
C++ delete 和 delete [] 简单结论: new delete new [] delete [] 文章 : 对 delete [] 的声明 void operator delete ...
- effective c++ 思维导图
历时两个多月的时间,终于把effective c++又复习了一遍,比较慢,看的是英文版,之前看的时候做过一些笔记,但不够详细,这次笔者是从头到尾的翻译了一遍,加了一些标题,先记录到word里面,然后发 ...
随机推荐
- (9)zabbix创建监控项item
1. 创建监控项 点击配置(configuration)->主机(Hosts)->在你要配置的主机一栏上点击Items->点击create item.具体看截图,各个参数我都已经标注 ...
- python-数字类型内置方法
数字类型内置方法 为什么要有数据类型? 数据是用来表示状态的,不同的状态就应该用不同的数据类型去表示 整型(int) 用途:年龄.号码.银行卡号等 定义:可以使用int()方法将纯数字的字符串转换为十 ...
- PAT Basic 1065
1065 单身狗 “单身狗”是中文对于单身人士的一种爱称.本题请你从上万人的大型派对中找出落单的客人,以便给予特殊关爱. 输入格式: 输入第一行给出一个正整数 N(≤ 50 000),是已知夫妻/伴侣 ...
- Action的实现方式
[Pojo方式] 1.概述 Pojo(Plain Ordinary Java Object)称为简单Java类,其实就是一个JavaBean. 2.示例 /** * Pojo类方式实现Action * ...
- 网址导航[IT]
一.Linux/UNIX Linux公社:http://www.linuxidc.com/index.htm Linux命令大全:http://man.linuxde.net 伯乐在线:http:// ...
- django基础(web框架,http协议,django安装)
学习Django之前我们先来看什么是OSI七层模型: 应用层 表示层 应用层(五层模型中把这三层合成一个应用层) http协议 会话层 传输层 提供端口对 ...
- 【bzoj3671】[Noi2014]随机数生成器 贪心
题目描述 输入 第1行包含5个整数,依次为 x_0,a,b,c,d ,描述小H采用的随机数生成算法所需的随机种子.第2行包含三个整数 N,M,Q ,表示小H希望生成一个1到 N×M 的排列来填入她 N ...
- BZOJ 1294 [SCOI2009]围豆豆Bean ——计算几何
显然我们不可能表示出一台路径,因为实在是太复杂了. 所以我们可以记录一下路径对答案的影响,显然路径对答案影响相同的时候,答案更优,所以我们可以用影响来代替路径. 所以我们考虑状压一下所有的豆子有没有被 ...
- 西南民大oj 1762 我的式子不可能那么难写 【波兰式】
描述 啦啦啦.作为一个苦逼的程序猿.?.请看下图... 现在老总想让你帮他儿子写个简单计算器(他儿子小学3年级,嘘!),写不出来就扣奖金..快帮他写吧... 给一个包含+-*/()的正确的表达式.要你 ...
- 算法复习——有源汇上下界可行流(bzoj2396)
题目: Description We are supposed to make a budget proposal for this multi-site competition. The budge ...