基于 http://www.cnblogs.com/diegodu/p/4555018.html operator new的知识基础上 介绍这个章节的内容

对于一般直接 new 与delete 性能较差,可以自己管理写内存的申请与释放。其实一般的operator new 和operator delete 直接调用 malloc 和 free的。

版本0:

class Rational
{
public:
Rational(int a=, int b = ): n(a),d(b){}
private:
int n;
int d;
};

版本1:专用的内存管理器

#include <stddef.h> // for size_t
#include <iostream> using namespace std; class NextOnFreeList {
public:
NextOnFreeList *next;
}; class Rational {
public:
Rational (int a = , int b = ) : n(a), d(b) {}
inline void *operator new(size_t size);
inline void operator delete(void *doomed, size_t size); static void newMemPool() { expandTheFreeList(); }
static void deleteMemPool(); private:
static NextOnFreeList *freeList; // A free list of Rational objects.
static void expandTheFreeList();
enum { EXPANSION_SIZE = }; int n; // Numerator
int d; // Denominator
}; inline
void * Rational::operator new(size_t size)
{
if ( == freeList) {// If the list is empty, fill it up.
expandTheFreeList();
} NextOnFreeList *head = freeList;
freeList = head->next; return head;
} inline
void Rational::operator delete(void *doomed, size_t size)
{
NextOnFreeList *head = static_cast <NextOnFreeList *> (doomed);
head->next = freeList;
freeList = head;
} void Rational::expandTheFreeList()
{
// We must allocate an object large enough to contain the next
// pointer.
size_t size = (sizeof(Rational) > sizeof(NextOnFreeList *)) ?
sizeof(Rational) : sizeof(NextOnFreeList *); // NextOnFreeList *runner = static_cast <NextOnFreeList *>(new char[size]);
NextOnFreeList *runner = (NextOnFreeList *)(new char[size]); freeList = runner;
for (int i = ; i < EXPANSION_SIZE; i++) {
//runner->next = static_cast <NextOnFreeList *> (new char[size]);
runner->next = (NextOnFreeList *)(new char[size]);
runner = runner->next;
} runner->next = ; cout << "expand" << endl;
} void Rational::deleteMemPool()
{
NextOnFreeList *nextPtr;
for (nextPtr = freeList; nextPtr != NULL; nextPtr = freeList) {
freeList = freeList->next;
delete [] nextPtr;
}
}
//测试code NextOnFreeList *Rational::freeList = ; int main()
{
Rational *array[]; Rational::newMemPool(); // Start timing here for (int j = ; j < ; j++) {
for (int i = ; i < ; i++) {
array[i] = new Rational(i);
}
for (int i = ; i < ; i++) {
delete array[i];
}
} // Stop timing here Rational::deleteMemPool(); return ;
}

这版本是通过重载 目标类 中的new 与delete 实现内存管理,只适用于目标类,但是速度是最快的。

实现方式是维护一个链表,类中静态声明链表头,链表维护一串空间,通过类型转换在  目标类 和 链表指针 之间转换。

如果内存不够(freelist=NULL)是一次申请较多内存进行维护。

链表的添加删除(对于函数释放空间与申请空间)是在链首操作。

书上47 行 52行通过 静态类型转换不成功,改为了 强制转换,在 g++ 中能够编译运行。

主要在主函数中调用静态函数 链表的申请与释放。

版本2:固定大小对象的内存池

考虑版本1,可以通过模板实现管理特定的对象。最主要的参数是类的大小。

实现是专门声明一个管理内存的内存池类,使用模板实现,提供alloc() free() 接口,给类申请与释放内存。

内存池类的实现是自身有一个MemoryPool<T>* next 指针用来指向维护的链表,内存的操作都在链首位置。

#include <stddef.h>
#include <iostream> using namespace std; template <class T>
class MemoryPool {
public:
MemoryPool (size_t size = EXPANSION_SIZE);
~MemoryPool (); // Allocate a T element from the free list.
inline void* alloc (size_t size); // Return a T element to the free list.
inline void free (void *someElement);
private:
// next element on the free list.
MemoryPool<T> *next; // If the freeList is empty, expand it by this amount.
enum { EXPANSION_SIZE = }; // Add free elements to the free list
void expandTheFreeList(int howMany = EXPANSION_SIZE);
}; template <class T>
MemoryPool <T> :: MemoryPool (size_t size)
{
expandTheFreeList(size);
} template < class T >
MemoryPool < T > :: ~MemoryPool ()
{
MemoryPool<T> *nextPtr = next;
for (nextPtr = next; nextPtr != NULL; nextPtr = next) {
next = next->next;
cout << nextPtr << endl;
//delete [] nextPtr;
//delete nextPtr;
delete [](char*)nextPtr; //不太明白为什么这样是对的,上面的方法不行。。
                    //明白了,因为new的时候就是用char字节的方法申请的,delete的时候要对应。。
}
} template < class T >
inline
void* MemoryPool < T > :: alloc (size_t)
{
if (!next) {
expandTheFreeList();
} MemoryPool<T> *head = next;
next = head->next; return head;
} template < class T >
inline
void MemoryPool < T > :: free (void *doomed)
{
MemoryPool<T> *head = static_cast <MemoryPool<T> *> (doomed); head->next = next;
next = head;
} template < class T >
void MemoryPool < T > :: expandTheFreeList(int howMany)
{
// We must allocate an object large enough to contain the
// next pointer.
size_t size = (sizeof(T) > sizeof(MemoryPool<T> *)) ?
sizeof(T) : sizeof(MemoryPool<T> *); //MemoryPool<T> *runner = static_cast <MemoryPool<T> *>(new char [size]);
MemoryPool<T> *runner = (MemoryPool<T> *)(new char [size]); next = runner;
for (int i = ; i < howMany ; i++) {
//runner->next = static_cast <MemoryPool<T> *> new char [size];
runner->next = (MemoryPool<T> *)( new char [size]);
runner = runner->next;
}
runner->next = NULL;
} class Rational {
public:
Rational (int a = , int b = ) : n(a), d(b) {} void *operator new(size_t size) { return memPool->alloc(size); }
void operator delete(void *doomed,size_t size)
{ memPool->free(doomed); } static void newMemPool() { memPool = new MemoryPool <Rational>; }
static void deleteMemPool() { delete memPool; }
private:
int n; // Numerator
int d; // Denominator static MemoryPool <Rational> *memPool;
}; MemoryPool <Rational> *Rational::memPool = ; int main()
{
Rational *array[]; Rational::newMemPool(); // Start timing here for (int j = ; j < ; j++) {
for (int i = ; i < ; i++) {
array[i] = new Rational(i);
}
for (int i = ; i < ; i++) {
delete array[i];
}
} // Stop timing here Rational::deleteMemPool(); }

efficient c++,单线程内存池的更多相关文章

  1. 内存池-转载自IBM

    [转载自IBM]讲的很好~推荐看看 6.1 自定义内存池性能优化的原理 如前所述,读者已经了解到"堆"和"栈"的区别.而在编程实践中,不可避免地要大量用到堆上的 ...

  2. C++实现简单的内存池

    多进程编程多用在并发服务器的编写上,当收到一个请求时,服务器新建一个进程处理请求,同时继续监听.为了提高响应速度,服务器采用进程池的方法,在初始化阶段创建一个进程池,池中有许多预创建的进程,当请求到达 ...

  3. golang 内存池

    一般来说,内存池都是采用预分配的方式,分为固定大小的和非固定大小块,固定大小的内存效率高,非固定大小灵活.同时,分为单线程和多线程版的,单线程不需要考虑并发问题. 一般内存池的实现思想:分配一块比较大 ...

  4. 内存分配(new/delete,malloc/free,allocator,内存池)

    以下来源http://www.cnblogs.com/JCSU/articles/1051826.html 程序员们经常编写内存管理程序,往往提心吊胆.如果不想触雷,唯一的解决办法就是发现所有潜伏的地 ...

  5. 基于C/S架构的3D对战网络游戏C++框架 _05搭建系统开发环境与Boost智能指针、内存池初步了解

    本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...

  6. berkeley db 内存池分配机制

    __memp_alloc() 注: MPOOL_ALLOC_SEARCH_DYN 没有 出现在 bdb document上, 也没出现在 除了mp_alloc外的代码里. 先删了 以便代码清楚. 按 ...

  7. NGINX 内存池有感

    写在前面 写NGINX系列的随笔,一来总结学到的东西,二来记录下疑惑的地方,在接下来的学习过程中去解决疑惑. 也希望同样对NGINX感兴趣的朋友能够解答我的疑惑,或者共同探讨研究. 整个NGINX系列 ...

  8. 【uTenux实验】内存池管理(固定内存池和可变内存池)

    1.固定内存池管理实验 内存管理是操作系统的一个基础功能.uTenux的内存池管理函数提供了基于软件的内存池管理和内存块分配管理.uTenux的内存池有固定大小的内存池和大小可变的内存池之分,它们被看 ...

  9. boost的线程池和内存池 智能指针

    内存池为boost自带的 #include <boost/pool/pool.hpp> 或者另外一个开源的库: nedmalloc 一个高效率的库 线程池需要下载另外一个开源库 http: ...

随机推荐

  1. C#中委托和事件的区别实例解析

    这篇文章主要介绍了C#中委托和事件的区别,并分别以实例形式展示了通过委托执行方法与通过事件执行方法,以及相关的执行流程与原理分析,需要的朋友可以参考下 本文实例分析了C#中委托和事件的区别,分享给大家 ...

  2. (转) 读取xml文件转成List<T>对象的两种方法

    读取xml文件,是项目中经常要用到的,所以就总结一下,最近项目中用到的读取xml文件并且转成List<T>对象的方法,加上自己知道的另一种实现方法. 就以一个简单的xml做例子. xml格 ...

  3. 深入探析koa之中间件流程控制篇

    koa被认为是第二代web后端开发框架,相比于前代express而言,其最大的特色无疑就是解决了回调金字塔的问题,让异步的写法更加的简洁.在使用koa的过程中,其实一直比较好奇koa内部的实现机理.最 ...

  4. 09_Java8操作集合的一些新特性

    [使用forEach()结合Lambda表达式遍历集合] public class ForEachDemo { public static void main(String[] args) { Col ...

  5. union 中可以存储的是不带构造函数的类对象

    union 中可以存储的是不带构造函数的类对象 否则不符合逻辑 为什么不符合逻辑?

  6. 3月3日(3) Binary Tree Preorder Traversal

    原题 Binary Tree Preorder Traversal 没什么好说的... 二叉树的前序遍历,当然如果我一样忘记了什么是前序遍历的..  啊啊.. 总之,前序.中序.后序,是按照根的位置来 ...

  7. bzoj 1005 HNOI2008 明明的烦恼

    这题做的我欲哭无泪啊…… 我已经没心情多说啥了…… 高精度T啊!我太弱啊!改了一天啊!还不如滚粗啊! 想好式子在写啊! 能用高精度乘单精度就不要用高精度乘高精度啊!     能用高精度除单精度就不要用 ...

  8. Poj OpenJudge 百练 2632 Crashing Robots

    1.Link: http://poj.org/problem?id=2632 http://bailian.openjudge.cn/practice/2632/ 2.Content: Crashin ...

  9. C++ VARIANT 学习小记录

    一:为什么会有这个? 目前,计算机语言有很多(大哥,为什么不能就那么一样呢?),如C++.Java,此外还有JavaScript.VBScript等脚本语言,它们自立门派,各自维护自己的数据类型. C ...

  10. java学习笔记_GUI(1)

    import javax.swing.*; public class Gui { public static void main(String[] args) { JFrame frame = new ...