对自定义的C++内存管理的一些总结!
来源:互联网 发布:微信投票系统 源码 编辑:程序博客网 时间:2024/06/02 04:24
说到内存管理就一定是与堆内存所联系,我们知道,自动变量是由栈来实现的,而堆内存是由程序员来控制管理的.
当我们有这样一段代码:
void * p=new TYPE NAME(constructor);
我们就申请了一块内存.这块内存对于程序员只是透明的一个占有sizeof(TYPENAME)大小的内存块.并在该内存上构造了这个类型的对象.
如果使用placement new实现原理也很简单,就是传递一个指针给new operator.这样当调用operator new时其实就是return 这个指针就可以了,接着在这块内存上构造对象.但这只是透明的.其实还有很多工作是要做的.
比如当我们申请一块内存时得到的内存一定比我们的类型所占内存要多,多出的内存是来记录这块内存的一些信息,比如它的大小.这样当delete的时候才能正确的释放.(可以看看我写的OPERATOR DELETE那篇文章)
上面所说的都是全局的标准函数.也就是::OPERATOR NEW()
如果想自己定义内存管理那就要在类中自己定义operator new ,operator delete了,记住一定要成对定义.就象刚才说的全局的new delete是有一些标准来互相传递信息的.你自己的new delete也一样.如果你只定义了NEW 那DELETE时候一定是会遇到麻烦的.
当我们在类中定义一个operator new 那当我们 NEW THIS CLASS的时候就会调用类中的operator new ,我们知道在类中的名字查找是这样的:当类中没有该名字就会在类外的作用域查找.但如果类中有这个名字,那就屏蔽外部的名字.也就是说不在去查找,接着才是进行参数匹配,寻找最合适的函数调用.所以说,如果你定义了operator new(size_t, new_handler) 当你写出void *p =new (ptr) classname;是对的,但如果你想 =new classname;则是错误的,因为全局operator new被屏蔽了,而且类中也没有operator new(size_t)这个函数原型.
有办法解决.例如可以在类中为自定义的operator new(size_t,new_handler)的第2个参数 设定一个默认值.operator new(size_t,new_handler=NULL)
或者在写一个operator new(size_t)来重载.在同作用域是可以重载的.
我们在来看看 new operator 和operator new 的联系.当我们=new classname 时会调用 operator new(sizeof(classname))
当我们多传递一个参数给operator new()当然可以直接用这个函数来调用,但如果通过new operator来实现要把第2个参数用这样的形式来传递 =new (参数) classname; 也就是说classname是第一个必须有的 传递给operator new函数的,而(参数)才是第2个参数.
上边说的placement new就是这样.不论operator new内部是怎么实现的,但透明给程序员的就是返回的这个指针 并在其上构造对象.
所以当我们自己写operator new 就要注意.虽然你可以为operator new多传递一个NEW HANDLER参数.来指明出现错误时调用的处理函数.但这样你可能就不能用=new (buffer ) classname;来实现placement NEW了 原因就是 你屏蔽了全局的operator new().
如果想实现PALCEMENT NEW 那就只能写出类似这样的代码
void * a::operator new(size_t ,void * y)
{
return y;
}
并且和全局函数一样 传递给他的VOID * 应该是之前申请好的内存地址.也就是用operator new(size_t)返回的指针.
当然当我们=new classname时 如果自己为类写了operator new(size_t) 会自动把size_t参数用SIZEOF(CLASSNAME)来初始化,就象全局函数一样简单.
例如我们想为类的内存实现内存池管理.我们只是第依次调用new classname时才真正调用了全局的operator new来分配一块很大的内存.以后的调用只是链表的造作.
所以一定要注意自己写operator new 时 和全局operator new的关系.
就着上边的内存池来说明为什么operator delete和new要成对出现.当编写了内存池管理时 我们调用new classname好几次的话就是在控制链表.但如果我们没有写operator delete 当我们delete 指针的话 是调用全局的 也就是说要参考那些封闭在底层 没有透明给程序员的那些信息,就是上边说的这块内存的大小信息等等.如果我们恰巧给了这块内存的首地址 那所有的内存就都释放了,而不是我们想要的释放一个对象的大小.而且即使是释放我们也只是希望操作链表 而不是真正释放.
- 对自定义的C++内存管理的一些总结!
- 对cocos2d内存管理的一些理解
- Linux的内存管理的一些总结
- 对 值班管理系统的一些总结
- cocos2d内存管理的一些学习总结
- 对X86内存管理架构的总结
- 【objective-c】内存管理中成员变量声明参数的一些总结
- 对插入排序以及内存管理的一些分析
- 对java内存回收机制的一些总结
- 内存管理的总结
- 【iOS7的一些总结】5、iOS中的内存管理
- boost shared_ptr 及C++内存管理的一些总结
- 关于内存管理思考方式的一些学习总结
- 嵌入式Linux内存管理的一些知识点总结
- linux2.4.0内存管理mmap_avl.c的一些思考记录
- 关于Objective-c内存管理的一些笔记
- Objective-C 关于内存管理的一些见解
- C.C++动态内存管理的一些问题
- ◎Vbs脚本编程简明教程之八—FSO中文件夹的基本操作
- 面试资料二
- C语言中的指针与数组
- 博客已搬新家
- 触发器(TRIGGER)对DB2数据库系统性能的影响
- 对自定义的C++内存管理的一些总结!
- 常用正则表达式
- ◎Vbs脚本编程简明教程之九—妙用SendKeys简化重复操作
- 刚刚完成的一个进程通信及托管非托管混合编程的总结之概述
- 短信接口
- ◎沉痛悼念FORTRAN之父逝世——一位越挫越勇的回头浪子
- 设定sql server定期自动备份数据库
- Solaris 9下安装Oracle 9操作指南
- 使用java.text包格式化数字和日期