您的位置:首页 > 编程语言 > C语言/C++

对自定义的C++内存管理的一些总结!

2007-07-16 16:13 453 查看
说到内存管理就一定是与堆内存所联系,我们知道,自动变量是由栈来实现的,而堆内存是由程序员来控制管理的.

当我们有这样一段代码:

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 指针的话 是调用全局的 也就是说要参考那些封闭在底层 没有透明给程序员的那些信息,就是上边说的这块内存的大小信息等等.如果我们恰巧给了这块内存的首地址 那所有的内存就都释放了,而不是我们想要的释放一个对象的大小.而且即使是释放我们也只是希望操作链表 而不是真正释放.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: