勤能补拙,Expter

成都游戏Coder,记录游戏开发过程的笔记和心得!

定制自己的new 和 delete,让对象在静态块上进行分配。

      一般常见的new和delete操作符,就意味着使用堆进行内存分配,使用new操作符是名为operator new的函数调用,且函数返回返回一个指向某块内存分配器分配内存指针。
      对于内存的分配到底从哪儿来没有任何限制,它可能来自一个特殊的堆,也可能来自一个静态分配的块,也可能来自一个标准容器内部,也可能来自某个函数范围的局部存储区。而对于现在的各自软件中主流内存管理方式,一般通过内存池的管理方式,它可能即包含静态分配也同时包含动态分配。
    其实网上关于内存池的设计很多,而本文主要简单的实现是一个对象可以从一个静态块上进行分配。
  

设计思路
        1.重载new 和delete,重写自己的内存分配方式。
        2.分配一大块静态数据,用于然后进行对象的管理。
        3.对于对象分配的空间,释放后通过一个链表来控制。
        4.每次对象分配先从空闲的链表中分配,然后在从静态块中分配,如果空间不足,跑出异常。
        5.并不会出现因分配空间失败,释放,以及内存泄露,所有的内存都在静态常量区,在程序结束后自动释放。 
      

可以通过运行结果分析:
       1.  2个对象的地址一样,内存值地址也是一样,对象可以进行静态块上的分配。
       2.  不会存在内存泄露。
       3.  浪费空间,碎片产生。

代码如下 :
  1#include <iostream>
  2#include <cstdlib>
  3using namespace std;
  4
  5class MyObjectMan;
  6
  7struct block
  8{
  9    enum { max = 1000 };
 10    
 11    union{
 12        char store[ 100 ];     /// 对于特定的对象,可以通过sizeof(Object);来避免浪费,
 13        block  *next;
 14    }
;
 15
 16    static block * free;
 17    static int num_used;
 18}
;
 19
 20block* block::free = NULL;            /// 空闲的列表
 21int  block::num_used = 0;
 22static block mem[ block::max ];       /// 静态存储块
 23
 24class MyObjectMan
 25{
 26    /// 
 27    /// 构造函数  Default constructor
 28    /// 

 29public:
 30    MyObjectMan( int _val , int _type): val(_val) , type(_type) 
 31    {
 32        std::cout <<" constructor  " << std::endl;
 33    }

 34
 35    ~MyObjectMan()
 36    {
 37        std::cout <<" disconstructor " << std::endl;
 38    }

 39
 40    void print()
 41    {
 42        std::cout << " val values  is  " <<  val 
 43                  << " type values is  " <<  type << std::endl;
 44    }

 45
 46    void OutAddress()
 47    {
 48        std::cout << " val values  is  " <<  &val 
 49                  << " type values is  " <<  &type << std::endl;
 50    }

 51    ///
 52    /// 重载new  delete  
 53    /// 

 54public:
 55    void * operator new ( size_t  t)        /// 分配空间
 56    {
 57        if ( block::free )                    /// 如果有空闲的列表,先从空闲列表中取出空间进行分配
 58        {
 59            block *tmp = block::free;
 60            block::free= block::free->next;
 61
 62            return tmp;
 63        }

 64        else if ( block::num_used < block::max )
 65        {
 66            return &mem[ block::num_used++ ]; /// 返回空闲区间
 67        }

 68        else                                /// 如果没有空闲区间
 69            throw 1;
 70    }

 71
 72    void operator delete( void  *p )        /// 添加到空闲的free list
 73    {
 74        static_cast<block * >(p)->next = block::free;  /// 采用的是链表的前插入
 75        block::free =  static_cast<block*>(p);
 76    }

 77
 78    /// 
 79    ///  var
 80    /// 

 81private:
 82    int val;
 83    int type;
 84
 85}
;
 86
 87int main()
 88{
 89    MyObjectMan *h1 = new MyObjectMan( 1 , 1);
 90    h1->print();
 91    h1->OutAddress();
 92    
 93    delete h1;
 94
 95
 96    MyObjectMan *h2 = new MyObjectMan( 2 , 2);
 97    h2->print();
 98    h2->OutAddress();
 99    delete h2;
100    
101

运行结果:
 constructor
 val values  is  1 type values is  1
 val values  is  0041A170 type values is  0041A174
 disconstructor
 constructor
 val values  is  2 type values is  2
 val values  is  0041A170 type values is  0041A174
 disconstructor

可以看出对象1,2地址一样,且内存中存储方式也一样。

posted on 2009-08-16 19:47 expter 阅读(2528) 评论(10)  编辑 收藏 引用 所属分类: 其他学习笔记生活笔记算法与数据结构

评论

# re: 定制自己的new 和 delete,让对象在静态块上进行分配。 2009-08-16 23:13 欲三更

内存池这个东西,除了在频繁的申请和释放小块内存的情况下以外,似乎也没有多大效率优势吧。如果单单为了防治内存泄漏启用内存池,会不会有点得不偿失?而且对于服务类软件,仅仅在软件结束运行的时候成功释放掉所有内存这种防泄漏方式,是很不够的,因为服务一般会运行很长时间。

不过内存池在调试的时候倒是蛮有用的。  回复  更多评论   

# re: 定制自己的new 和 delete,让对象在静态块上进行分配。 2009-08-16 23:19 月下饮者

拜读了。。。  回复  更多评论   

# re: 定制自己的new 和 delete,让对象在静态块上进行分配。 2009-08-16 23:39 expter

@欲三更
你说的对于服务类软件,一般都会使用内存池通过空间换取时间,而且分配方式一般会使用静态分配和动态2种,所以软件结束这种应该是一般内存池都有的。
而我这里只是重写new,delete,让对象可以在静态块上进行分配。  回复  更多评论   

# re: 定制自己的new 和 delete,让对象在静态块上进行分配。 2009-08-17 02:14 欲三更

@expter
你这个重载的new其实不就是个mempool么?只不过分配的空间大小是个常数而已。  回复  更多评论   

# re: 定制自己的new 和 delete,让对象在静态块上进行分配。[未登录] 2009-08-17 08:59 expter

@欲三更
嗯。。
哇 你那么晚还没睡觉  回复  更多评论   

# re: 定制自己的new 和 delete,让对象在静态块上进行分配。 2009-08-17 10:41 absolute

你能确保你的block一定适合任意大小的对象?
char store[ 100 ];这个一定够用?

而且这样内存无疑会有巨大浪费,除非能动态配置大小.  回复  更多评论   

# re: 定制自己的new 和 delete,让对象在静态块上进行分配。[未登录] 2009-08-17 23:25 欲三更

@absolute
呵呵,我又来了:P
在只有debug使用的情况下,选个大差不差的常数就好了,狼不浪费其实也没什么关系,我自己要是搞这种东西一般都是为了查查内存泄露什么的  回复  更多评论   

# re: 定制自己的new 和 delete,让对象在静态块上进行分配。[未登录] 2009-08-18 04:56 fox

重载NEW唯一坏处是线程不安全。  回复  更多评论   

# re: 定制自己的new 和 delete,让对象在静态块上进行分配。 2009-08-19 14:42 12530彩铃

啊按时打算的  回复  更多评论   

# re: 定制自己的new 和 delete,让对象在静态块上进行分配。 2009-08-22 14:36 陈s

你的留言板在哪里!我已做好你的链接,有空去写写书啊!为了中国it业的共同发展!  回复  更多评论   


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理