7.预先准备足够的内存情况。

new当内存分配请求无法完成,它会抛出一个异常,怎么办异常,这是一个非常现实的,绝对必要的所遇到的问题后。

于c一般使用宏来分配内存和测试分发成功。c++中产阶级似下面的函数:

#define NEW(PTR,TYPE)    \
try { (PTR) = new TYPE;} \
catch (std::bad_alloc& ){assert(0);}

catch 的std::bad_alloc为new 操作符中 不能满足内存分配请求时抛出的异常类型。

assert是在<assert.h>中宏,或者带命名空间的<cassert> 。宏检測传给它的表达式的值是否为0,假设是0,就会发出一条出错信息,并调用abort。assert在未定义标准宏NDEBUG时,即仅仅在调试状态中这么做。当产品公布后,即定义了NDEBUG后,assert什么也不做。

但使用宏是不够的,由于其仅仅能进行简单的一个基本数据类型的内存分配,而对于数组以及有构造函数的数据类型无法使用。

能够考虑重载operator new 。

而经常使用的简单的出错处理方法是,通过设置一个出错处理函数,使内存分配请求不能满足时,调用这个处理函数。

由于operator new 操作符在不能满足请求时。会在抛出异常前调用客户指定的一个出错处理函数。这个函数称为new-handler函数。

指定出错处理函数要用到set_new_handler 函数,该函数位于头文件<new>中,其定义例如以下:

new_handler __cdecl set_new_handler(_In_opt_ new_handler)
_THROW0();

而new_handler的定义例如以下:

typedef void (__cdecl * new_handler) ();

new_handler为指向一个没有參数没有返回值的函数。而set_new_handler函数是一个输入參数为 operator new 分配内存失败时调用的出错处理函数的指针。返回值为set_new_handler函数没调用之前的已经在起作用的旧的函数处理函数的指针。

用法例如以下:

void noMoreMemory(){
cerr<<"123";
abort();
}
int main(){
set_new_handler(noMoreMemory);
int *p = new int [ 0x1fffffff ];

真正在程序中,new_handler函数不是简单的检測出错然后停止程序。而是要去处理出错,即通过一些措施,使下次内存分配能够成功。一个好的new_handler函数从下面几个方向入手:

1.产生很多其它的可用内存。若在程序启动时预留一大块内存。

然后失败时释放出这些内存供使用。

2.安装还有一个不同版本号的new_handler函数。通过一个新的能够获得资源的函数来获得很多其它资源,或者使用一些全局变量来改变自身的行为。

3.卸载new_handler。

分配无法成功,直接返回抛出标准的std::bad_alloc异常。

4.抛出bad_alloc异常或bad_alloc的派生异常。

5.没有返回,即如上所看到的,调用abort或exit。

类中的内存分配出错能够有自己重载的类的new操作符和 set_new_handler来实现。而这些函数与重载都是类的静态成员。

首先,类中要有一个静态成员 currentHandler来保存当前使用的new_handler函数。

对于set_new_handler。它仅仅是将类内的指针进行更换,以及返回旧的指针。而标准版本号也是如此做的。

对于operator new 。类中的重载new操作符,仅仅是简单的调用原有的new操作符操作,仅仅是错误处理用上类中设置的新的出错处理函数,所以其做法仅仅是用全局的set_new_handler()设置当前类中的currentHandler为处理函数,分配内存后或者异常报错前,恢复就可以。

代码例如以下:

class A{
public:
static void* operator new (size_t size);
static new_handler set_new_handler(new_handler p);
private:
static new_handler currentHandler;
};
new_handler A::currentHandler;
new_handler A::set_new_handler(new_handler p){
new_handler t = currentHandler;
currentHandler = p;
return t;
}
void* A::operator new(size_t size){
new_handler globalHandler = std::set_new_handler(currentHandler);
void* memory;
try{
memory = ::operator new(size);//::operator new 表示为全局的new操作符。 }
catch(std::bad_alloc&){
std::set_new_handler(globalHandler);
throw;
}
std::set_new_handler(globalHandler);
return memory;
}

而要做到非常好的代码重用,即对不论什么一个类都能轻松的实现以上代码实现的内容,能够创建一个混合风格的基类,这样的基类同意子类继承它的某一特定功能,如这里的new操作符的出错处理。

混合风格?43.

版权声明:本文博主原创文章,博客,未经同意不得转载。

Effective C++ 7的更多相关文章

  1. Effective前端2:优化html标签

    div { float: left; } .keyboard > div + div { margin-left: 8px; } --> div{display:table-cell;ve ...

  2. Effective java笔记(二),所有对象的通用方法

    Object类的所有非final方法(equals.hashCode.toString.clone.finalize)都要遵守通用约定(general contract),否则其它依赖于这些约定的类( ...

  3. 《Effective java》-----读书笔记

    2015年进步很小,看的书也不是很多,感觉自己都要废了,2016是沉淀的一年,在这一年中要不断学习.看书,努力提升自己!预计在2016年要看12本书,主要涉及java基础.Spring研究.java并 ...

  4. 《Effective Java》学习笔记——积累和激励

    从一个实际案例说起 国庆长假前一个礼拜,老大给我分配了这么一个bug,就是打印出来的报表数量为整数的,有的带小数位,有的不带,毫无规律. 根据短短的两个多月的工作经验以及猜测,最终把范围缩小到以下这段 ...

  5. Effective前端5:减少前端代码耦合

    什么是代码耦合?代码耦合的表现是改了一点毛发而牵动了全身,或者是想要改点东西,需要在一堆代码里面找半天.由于前端需要组织js/css/html,耦合的问题可能会更加明显,下面按照耦合的情况分别说明: ...

  6. Effective前端4:尽可能地使用伪元素

    伪元素是一个好东西,但是很多人都没怎么用,因为他们觉得伪元素太诡异了.其实使用伪元素有很多好处,最大的好处是它可以简化页面的html标签,同时用起来也很方便,善于使用伪元素可以让你的页面更加地简洁优雅 ...

  7. Effective前端3:用CSS画一个三角形

    p { text-indent: 2em } .triangle-container p { text-indent: 0 } img { margin: 15px 0 } 三角形的场景很常见,打开一 ...

  8. Effective前端1:能使用html/css解决的问题就不要使用JS

    div{display:table-cell;vertical-align:middle}#crayon-theme-info .content *{float:left}#crayon-theme- ...

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

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

  10. effective java 读后感

    think in java  , effective java  这两本书一直都在java的生态圈中经久不衰.本来想着先翻过 think in java 这本大山,但是读到一半就放弃了.过长的篇幅,让 ...

随机推荐

  1. Windows Azure应用系列:微软的云部署VPN

    本文介绍如何使用OpenVPN微软云计算server既定VPN维修. 过程,如下面: 1.新建Linux或者Ubuntu虚拟机.并设置port.(本文将建立Ubuntu作为演示) 2.利用PuTTY登 ...

  2. WCF基金会

    概念: Windows CommunicationFoundation(WCF)是由微软发展的一组数据通信的应用程序开发接口.能够翻译为Windows通讯接口.它是.NET框架的一部分. 简单地说,W ...

  3. 从头开始建网站(三)DNS

    前面介绍了站点搭建所须要的两大要素:域名和server,这次要说的是域名解析,也就是把域名和server进行绑定的过程. 我们在訪问网络时,网址会被发送到DNSserver,然后由DNSserver返 ...

  4. wind river hypervisor 2.0.2.1

    2692407267@qq.com,请注意很多其他内容http://user.qzone.qq.com/2692407267 wind river hypervisor 2.0.2.1 版权声明:本文 ...

  5. poj 1384 Piggy-Bank(全然背包)

    http://poj.org/problem?id=1384 Piggy-Bank Time Limit: 1000MS Memory Limit: 10000K Total Submissions: ...

  6. 笔试题&amp;面试题:输入一个维度,逆时针打印出一个指定矩阵

    称号:考虑到用户层面.打印出指定的矩阵,例如,一个给定的用户10,例如,下面的输出应被视为在图: 程序如下所示: #include <stdio.h> #include <mallo ...

  7. Oracle 11G DataGuard生产环境又一次启动具体过程

     场景,重新启动数据库,不重新启动linux系统,所以不用考虑监听程序,#linux输入lsnrctl start1 数据库关闭1.1 关闭主库SHUTDOWN IMMEDIATE; SQL> ...

  8. ICT工作的思考&lt;两&gt;

    2周奋战.我负责的LB昨天完成了最后一个模块.最后20日. 一周早于预期,经理说,出乎他的意料.So 奖励表,昨日,管理人员与我们合作,吃烧烤补补身子.我只想说,最后一个喘息. 这两周的生活确挺忙碌的 ...

  9. MariaDb数据库管理系统的学习(一)安装示意图

    MariaDB数据库管理系统是MySQL的一个分支.主要由开源社区在维护,採用GPL授权许可.开发这个分支的原因之中的一个是:甲骨文公司收购了MySQL后,有将MySQL闭源的潜在风险,因此社区採用分 ...

  10. Cocos2d-x 3.2 Lua演示样本CocosDenshionTest(音频测试)

    Cocos2d-x 3.2 Lua演示样本CocosDenshionTest(音频测试)  本篇博客介绍Cocos2d-x 3.2中Lua演示样例的音频測试.Cocos2d-x使用SimpleAudi ...