惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
云风的 BLOG
云风的 BLOG
B
Blog
博客园 - Franky
I
InfoQ
A
About on SuperTechFans
博客园_首页
L
LangChain Blog
量子位
腾讯CDC
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
美团技术团队
V
V2EX
Apple Machine Learning Research
Apple Machine Learning Research
雷峰网
雷峰网
MongoDB | Blog
MongoDB | Blog
Microsoft Azure Blog
Microsoft Azure Blog
月光博客
月光博客
T
The Blog of Author Tim Ferriss
P
Proofpoint News Feed
G
Google Developers Blog
Last Week in AI
Last Week in AI

博客园 - liuchen

我回来了 《全景探秘游戏设计艺术》读后感之引子 长连接和短连接 这不科学 —— 读《死亡之旅》 windows 64位 luajava编译 Effective C++ 读书笔记(45-50):杂项讨论 Effective C++ 读书笔记(35-44):继承关系与面向对象设计 Effective C++ 读书笔记(29-34):类与函数之实现 Effective C++ 读书笔记(18-28):类与函数之设计和声明 Effective C++ 读书笔记(11-17):构造析构和赋值函数 - liuchen Effective C++ 读书笔记(0-4) - liuchen 读《msyql完全手册》之三:管理与开发 读《msyql完全手册》之二:数据库使用 读《msyql完全手册》之一:介绍和安装 js中的定时器 php中readdir关于时间路径排序的代码 linux 配置服务器 Windows下配置SVN (Subversion) 转载 该适当的总结了
Effective C++ 读书笔记(5-10):内存管理
liuchen · 2009-10-10 · via 博客园 - liuchen

Item5:使用相同形式的new和delete

简单的说,就是单个对象和数组要区分对待。C++使用[]区分这是单个对象还是数组,所以new中有[]的时候,请用delete[]。

Item6:记得在destructor中以delete对付pointer member

这条为了防止内存泄露,具体说来要做三件事情:

  1. 每个构造函数中将该指针初始化
  2. 每个赋值运算符中将原有内存删除,重新配置一块
  3. 每个析构函数中,delete这个指针

Item7:为内存不足的状况预作准备

operator new申请内存得不到满足时,在抛出std::bad_alloc之前会调用用户设置的handler,该调用找到足够的内存才停止

typedef void(*new_handler)();

new_handler set_new_handler(new_handler p) throw();

因此,自己定义new handler需要遵循以下原则:

  1. 让更多内存可用
  2. 自己处理不了的情况下,安装一个不同的new handler
  3. 卸载这个new handler,抛出std::bad_alloc
  4. 直接调用abort或者exit

现在标准的operator new的行为时抛出一个std::bad_alloc的异常,其实,现在很少有情况会无法申请到内存,按照标准的做法即可。在抛出bad_alloc异常之后,做好log记录和分析,一旦遇到这种情况,加内存就是了。

Item8:撰写operator new和operator delete时应遵行的公约

自己写operator new,要和缺省的行为保持一致,详细说来,new应该遵循的公约如下:

void * operator new(size_t size)

{

if(size==0){ //1.大小为0的new也可以成功

size=1;

}

while(true){ //2.不断循环,尝试申请内存

if(alloc success) return *pointer //3.成功返回指针

//4.不成功,处理错误

new_handler globalHandler = set_new_handler(0);

set_new_handler(globalHandler);

if(globalHandler) (*globalHandler)();

else throw std::bad_alloc(); //5.没有处理函数,则抛异常

}

}

delete应该遵循的则很简单,即删除一个null指针永远是安全的

void operator delete(void * rawMemory)

{

if(rawMemory ==0 ) return;

否则再删除内存

}

Item9:避免遮掩了new的正规形式

C++中,内部scope中的声明会遮掩外部的相同名称,条款9说明了一个特殊情况,自己写了一个定制的operator new,接收一个new_handler做额外的参数如下

void * operator new(size_t size, new_handler p)

这个operator new会遮掩缺省的operator new,用户无法调用默认的new操作,针对这个情况,有两种解决方法,一种是再声明一个operator new(size_t size),另一种则是采用默认参数operator new(size_t size, new_handler p=0)

Item10:如果你写了一个operator new,请对应写一个operator delete

条款10其实说明使用operator new的原因:提高内存空间使用效率。

缺省的operator new需要在返回指针的前方使用一点空间记录该指针占用的大小(该空间称作cookie),用于delete的正常运行。自己重载operator new,则可以自己进行管理这个区块,减少内存使用

实现内存池,每次从内存池中申请,若内存池也不够的话,则扩张之

所以,写了一个operator new之后,要对应写一个operator delete,因为只有自己才知道到底是如何申请内存的。