现在的位置: 首页 > 综合 > 正文

内存管理:频繁申请大量(同等大小)小对象的优化内存策略

2013年10月03日 ⁄ 综合 ⁄ 共 1613字 ⁄ 字号 评论关闭

《Effective C++》中的条款10  如果写了operator new就要同时写operator delete 一节
给出了一个很精妙的例子。给出了一个最简单的内存池的模型。

读起来让人真感觉的舒服。。。

实现方法就是 类中重载了operate new, delete 操作符。申请大内存,切分成小内存,依靠链表的形式组织起来。。反复利用。。貌似没有处理内存不够用时的动态增长内存的情况。

上代码:

// 类定义

class airplane {           // 修改后的类 — 支持自定义的内存管理
public:                    //

  static void * operator new(size_t size);

  ...

private:
  union {
    airplanerep *rep;      // 用于被使用的对象
    airplane *next;        // 用于没被使用的(在自由链表中)对象
  };

  // 类的常量,指定一个大的内存块中放多少个
  // airplane对象,在后面初始化
  static const int block_size;

  static airplane *headoffreelist;

};

 

// 重载new

void * airplane::operator new(size_t size)
{
  // 把“错误”大小的请求转给::operator new()处理;
  // 详见条款8
  if (size != sizeof(airplane))
    return ::operator new(size);

  airplane *p =           // p指向自由链表的表头
    headoffreelist;       //

  // p 若合法,则将表头移动到它的下一个元素
  //
  if (p)
    headoffreelist = p->next;

  else {
    // 自由链表为空,则分配一个大的内存块,
    // 可以容纳block_size个airplane对象
    airplane *newblock =
      static_cast<airplane*>(::operator new(block_size *
                                            sizeof(airplane)));

    // 将每个小内存块链接起来形成一个新的自由链表
    // 跳过第0个元素,因为它要被返回给operator new的调用者
    //
    for (int i = 1; i < block_size-1; ++i)
      newblock[i].next = &newblock[i+1];

    // 用空指针结束链表
    newblock[block_size-1].next = 0;

    // p 设为表的头部,headoffreelist指向的
    // 内存块紧跟其后
    p = newblock;
    headoffreelist = &newblock[1];
  }

  return p;
}

 

// 传给operator delete的是一个内存块, 如果
// 其大小正确,就加到自由内存块链表的最前面
//
void airplane::operator delete(void *deadobject,
                               size_t size)
{
  if (deadobject == 0) return;         // 见条款 8

  if (size != sizeof(airplane))     {  // 见条款 8
    ::operator delete(deadobject);
    return;
  }

  airplane *carcass =
    static_cast<airplane*>(deadobject);

  carcass->next = headoffreelist;
  headoffreelist = carcass;

抱歉!评论已关闭.