//---------------------------15/04/27----------------------------

//#49   了解new-handler的行为

{

/*

1:在operator new操作失败时,它首先会调用new_handler函数来处理,客户可以通过set_new_handler

的函数来设置new_handler函数。

2:一个设计良好的new_handler必须做以下事情:

1>让更多内存可被用:

程序一开始执行就分配一大块内存,而后当new_handler第一次被调用,将这块内存释放还给程序使用。

2>安装另一个new_handler:

如果这个handler知道另外一个handler有能力获得更多的内存,就可以选择安装那个handler

3>卸载new_handler:

一旦没有安装new_handler,operator new会在内存分配不成功时抛出异常。

4>抛出bad_alloc异常:

这样的异常会被传播到内存索求处。

5>不返回:

通常调用abort或exit。

这里有一点很重要:new_handler必须执行以上5个选项之一,因为如果设置了一个没用的new_handler,

比如:void dosomething() { cout<<"error"<<endl;}

那么系统就会无限执行这条语句了。

3:设计一个属于class的new_handler:

1>先使用资源管理对象,把class专属的new_handler保存到资源管理对象

2>重载operator new调用标准的set_new_handler,设置之前保存的的new_handler,

这会将class的new_handler安装为global new_handler。

2>调用global operator new,执行内存分配,如果内存分配失败,global operator new函数会调用

之前安装的class专属new_handler。

3>资源管理对象会自动恢复global new_handler。

4:设计一个可复用的class用来支持class的专属new_handler:              
          */

template<class T>

class NewHandlerSupport

{

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;

};

template<class T>

std::new_handler

NewHandlerSupport<T>::set_new_handler(std::new_handler p)
throw()

{

std::new_handler oldHandler = currentHandler;

currentHandler = p;

return oldHandler;

}

template<class T>

void* NewHandlerSupport<T>::operator new(std::size_t size)throw(std::bad_alloc)

{

NewHandlerHolder h(std::set_new_handler(currentHandler));

return ::operator new(size);

}

template<class T>

std::new_handler NewHandlerSupport<T>::currentHandler =
;

//这里唯一困惑的就是为什么要使用模版,模版的作用就是为了达到一个效果:每一个类都可以有自己的

//静态变量(currentHandler),不然大家的currentHandler就一样了。

}

//#50   了解new和delete的合理替换时机

{

/*

1:为什么要替换编译器提供的operator new和operator delete

1>用来检测运用上的错误:

我们可以在客户请求的大小外(前后)多分配一些内存,用来存放标记。如果delete的时候标记被改变了

就说明被分配的内存的前面或后面被写了,也就是客户操作越界了。这样就可以检测出错误。

2>为了强化效能:

编译器提供的new和deletet为了满足所有人的需求,所以会比较笨重,此时为了需求

我们可以定制自己的new和delete。这是一个获得重大效能提升的办法之一。

sgi-stl中,就把128k以下的内存申请交给自己管理,对128k以上的内存使用malloc处理,原因

是,系统对于小内存的分配会比较慢(相对于我们自己处理来说,因为它总是要记录一些信息,还要考虑

产生碎片的问题等等)。

3>为了收集使用上的统计数据:

收集很多数据:分配区块的大小分布如何?寿命分布如何?是FIFO(先进先出)还是LIFO(后进先出)等等。。。

2:自己定制operator new
要注意一个问题:

对齐问题,malloc返回的指针总是对齐的,所以如果我们在malloc返回的指针前面加上int类型大小的标记

那么,针对double类型来说,它是不对齐的。

3:总结合适替换new和delete:

1>为了检测运用错误

2>为了收集动态分配内存之使用统计信息

3>为了增加分配和归还的速度

4>为了降低缺省内存管理器带来的空间额外开销

5>将相关对象放在一起:

这样有助于提高高速缓存的命中率。

6>为了获得非传统行为

*/

}

//#51   编写new和delete时需固守常规

{

/*

1:记得调用new_handler

2:为了不把operator new被子类继承,检测一下new需要申请的大小,只要不等于Base,就调用

全局的new。

3:重载delete的时候记得检查NULL指针,这种情况应该直接返回,因为编译器总是允许delete NULL。

*/

}

//#52   写了placement new也要写placement delete

{

/*  1:写了一个placement operator new的时候,要确定写出了对应的delete版本,不然就会发生内存泄漏。

2:写了placement版本的new时可能会遮盖正常版本的new,所以要实现正常版本的调用,比如:

static void* operator new(std::size_t size) throw(std::bad_alloc)

{ return ::operator new(size);}

}

effective c++ 笔记 (49-52)的更多相关文章

  1. [Effective JavaScript 笔记]第52条:数组字面量优于数组构造函数

    js的优雅很大程序要归功于程序中常见的构造块(Object,Function及Array)的简明的字面量语法.字面量是一种表示数组的优雅方法. var a=[1,2,3,5,7,8]; 也可以使用构造 ...

  2. Effective Java笔记一 创建和销毁对象

    Effective Java笔记一 创建和销毁对象 第1条 考虑用静态工厂方法代替构造器 第2条 遇到多个构造器参数时要考虑用构建器 第3条 用私有构造器或者枚举类型强化Singleton属性 第4条 ...

  3. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  4. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  5. [Effective JavaScript 笔记]第3章:使用函数--个人总结

    前言 这一章把平时会用到,但不会深究的知识点,分开细化地讲解了.里面很多内容在高3等基础内容里,也有很多讲到.但由于本身书籍的篇幅较大,很容易忽视对应的小知识点.这章里的许多小提示都很有帮助,特别是在 ...

  6. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  7. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  8. java effective 读书笔记

    java effective 读书笔记 []创建和销毁对象 静态工厂方法 就是“封装了底层 暴露出一个访问接口 ” 门面模式 多参数时 用构建器,就是用个内部类 再让内部类提供构造好的对象 枚举 si ...

  9. Effective STL 笔记 -- Item 6 ~ 7: Container and Object Pointer

    Effective STL 笔记 – Item 6 ~ 7: Container and Object Pointer 中间两次笔记被删掉了,简单补一下: Item 3 中提到如果将对象直接放入容器中 ...

  10. Item 5:那些被C++默默地声明和调用的函数 Effective C++笔记

    Item 5: Know what functions C++ silently writes and calls 在C++中,编译器会自己主动生成一些你没有显式定义的函数,它们包含:构造函数.析构函 ...

随机推荐

  1. 适用于 Windows 的自定义脚本扩展

    自定义脚本扩展在 Azure 虚拟机上下载并执行脚本. 此扩展适用于部署后配置.软件安装或其他任何配置/管理任务. 可以从 Azure 存储或 GitHub 下载脚本,或者在扩展运行时将脚本提供给 A ...

  2. 如何避免SHRINKDATABASE & SHRINKFILE 产生索引碎片(转载)

    1. TRUNCATEONLY参数的使用我们在建立的Job中通常使用如下的语法DBCC SHRINKDATABASE (N'DB', 10,TruncateOnly)其中TruncateOnly的用处 ...

  3. NewEmployeesLearnNotes——新人程序员学习计划V1.1

    百度云链接:https://pan.baidu.com/s/1BzoT79tV1QGwIQTjkGA4CQ 密码:k78i 修改中...

  4. beta冲刺————第五天(5/5=1)

    今天的主要内容是前后端的对接: 通过前几天的对接,我们发现后端传给前端内容是可以很完美的显示出来的,说明文章格式以及一些默认规则都是OK的. 然后就是前端从云服务器上面接受到文章的具体内容,在这一个环 ...

  5. beta冲刺————第四天(4/5)

    完善的具体内容: 前端:以下的功能还未完全实现 (1)点击收藏可以收藏入收藏夹 (2)分享操作,意见反馈 后端: 寻找文章来源,像数据库中增添了150篇的新文章.(我们的文章都要求自己内部人员看过,所 ...

  6. django复习-2-配置、静态文件与路由

    一.配置文件 1. BASE_DIR BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) __file__指当 ...

  7. String真的是不可变的吗?

    你可能问一个人String是可变的吗?想必他们都会一口同生的说String是不可变的,因为String是final修饰的,而且它底层的是final修饰的char[]数组. 可以看到String源码: ...

  8. sed 指定行范围匹配(转)

    sed -n '5,10{/pattern/p}' file sed是一个非交互性性文本编辑器,它编辑文件或标准输入 导出的文件拷贝.标准输入可能是来自键盘.文件重定向.字符串或变量,或者是一个管道文 ...

  9. 如何弹出QQ临时对话框实现不添加好友在线交谈效果

    如何不添加好友弹出QQ临时对话框实现在线交谈效果,这样的一个需求,我们真的是太需要了,实现起来也很简单,一行代码即可搞定,需要的朋友可以参考下 其实这个很简单,在img我们加入一个a标签,然后 < ...

  10. CF558E A Simple Task

    题目大意: 给定一个长度不超过10^5的字符串(小写英文字母),和不超过5000个操作. 每个操作 L R K 表示给区间[L,R]的字符串排序,K=1为升序,K=0为降序. 最后输出最终的字符串 首 ...