设计一个小型的内存池以及链表

上一节撸到万事俱备只欠真正的lex, 但是lex的作用是将源代码转化为Token流, 用什么保存Token? 这就涉及到我们要接触的第一个数据结构—链表, 虽然标准库中很多容器都可以承担链表的任务, 但是我说过出于锻炼原因, 我会尽量不使用stl中的容器, 所以我决定自己撸一个链表出来, 既然之后大多数的容器都要自己撸, 干脆连内存池也一并撸一个出来, 所以这一节的两个目的就是 : 内存池以及基于这个内存池的链表.

我个人接触内存池的时间不长, 准确的说我目前脑袋里面只有两中内存池的思路, 一种是sgi stl内存池,我之前有一篇文章专门对这种内存池做过讲解, 但是这里我会使用另外一种较为简易的内存池模型, 因为我认为sgi stl准确来说可以支持频繁地不同大小的内存分配, 而我这里会使用一种简化的思路, 使之每一个内存池只支持单一大小的内存分配. 这种内存池也是从别人那里学过来的, 简图差不多是这样.

然后源代码差不多是这样...

#ifndef FRED_MEMORYPOOL_H
#define FRED_MEMORYPOOL_H#include <cstdio>
#include <cstdlib>
#include <vector>template <typename T, size_t NumberForOneNode = 32>
class MemoryPool{
private:struct node{void* space;node* next;};node *head, *tail;size_t left;void* cur;protected:MemoryPool():left(NumberForOneNode){tail = head = new node;head->next = 0;cur = head->space = static_cast<T*>(malloc(sizeof(T) * NumberForOneNode));}//Big threeMemoryPool(const MemoryPool&) = delete;MemoryPool& operator=(const MemoryPool& rhs) = delete;~MemoryPool();void* allocate();
};template <typename T, size_t NumberForOneNode>
MemoryPool<T, NumberForOneNode>::~MemoryPool() {while(true) {if (head == tail) {free(head->space);delete head;return;}auto temp = head;head = head->next;free(temp->space);delete temp;}
}template <typename T, size_t NumberForOneNode>
void* MemoryPool<T, NumberForOneNode>::allocate() {if(left--){auto re = cur;cur = reinterpret_cast<char*>(cur) +sizeof(T);return re;}left = NumberForOneNode;auto newNode = new node;newNode->next = 0;tail = tail->next = newNode;cur = newNode->space = static_cast<T*>(malloc(sizeof(T) * NumberForOneNode));allocate();
}#endif //FRED_MEMORYPOOL_H

图上的变量和代码里面的变量名字都是统一的, 很好理解...

这个内存池的最后一步, 是在这个内存池的基础上, 再套一层封装.

#ifndef FRED_ALLOCATOR_H
#define FRED_ALLOCATOR_H#include "MemoryPool.h"template <typename T, size_t NumberForOneNode = 32>
class Allocator : private MemoryPool<T, NumberForOneNode> {
private:void* buffer[NumberForOneNode];size_t left;public:Allocator():left(0){};void* allocator(){if(left){return buffer[--left];}else{return MemoryPool<T, NumberForOneNode>::allocate();}}void deallocator(T* ptr){ptr->~T();if(left == NumberForOneNode){//fullreturn;}       buffer[left++] = ptr;}
};#endif //FRED_ALLOCATOR_H

思想其实很简单, 就是如果有空间被送回, 并不直接交还给系统, 而是用这个叫做buffer的数组存着, 如果之后再有需要, 优先从数组中取, 其实这里用vector要比buffer更好, 但是如果想要重利用的空间规模不大的话, buffer也够用, 就算这个buffer也不会内存泄漏, 只是有一些空间被浪费了, 等到维护这个allocator的类卒了, 空间还是要被释放的.

如果想看这个内存池的原版本实现, 可以看这里

原版本实现

有了内存池, 根据我们的需求我们只需要一个链表.

#ifndef FRED_LINKLIST_H
#define FRED_LINKLIST_H#include "MemoryPool/Allocator.h"template <typename T>
class LinkList{
private:struct node{T item;struct node* next;};Allocator<node> allocator;node* head;node* cur;size_t size;public:LinkList():head(0), cur(0), size(0){}LinkList(const LinkList&) = delete;LinkList& operator=(const LinkList&) = delete;~LinkList(){for(auto temp = head; temp != cur; temp = temp->next){allocator.deallocator(temp);}allocator.deallocator(cur);}void pushBack(const T& item){if(cur) {cur = cur->next = reinterpret_cast<node*>(new(allocator.allocator())T(item));}else {cur = head = reinterpret_cast<node*>(new(allocator.allocator())T(item));}++size;cur->next = 0;}node* getHead() const {return head;}
};#endif //FRED_LINKLIST_H

对于这个链表功能和实现都很简单, 这里唯一要说可能有些人不知道new可以指定空间进行初始化, 不知道的可以去网上看一下, 这是placement new而我们一般使用的带有内存分配的叫做plain new...

大概就是这么多, 这个礼拜在成都玩, 可能更新地比较慢...

转载于:https://www.cnblogs.com/nzhl/p/5767851.html

Lexer的设计--中(4)相关推荐

  1. 【转】Android设计中的.9.png

    来源:http://isux.tencent.com/android-ui-9-png.html Android设计中的.9.png 注意:当使用9.png做TextView背景时,一定要设置内容区域 ...

  2. EMC设计中电缆屏蔽使用方法

    在EMC 设计中,电缆进行屏蔽的目的有两方面: 将注入到电缆的共模干扰电流通过屏蔽层引导到大地(接地设备)或PCB中的工作地GND(浮地设备),使屏蔽层中的信号和电缆接口电路受到保护,免受外界干扰: ...

  3. 设计中涉及到的dip、dp、px、sp等单位说明

    在进行UI设计中常会遇到各种数值单位,开始使用时也常搞混,于是搜集了单位解说的文章与大家一同分享 dip: device independent pixels(设备独立像素). 不同设备有不同的显示效 ...

  4. 软件可读性和效率取舍_网络通信设计中的一些限制和取舍:摘要

    软件可读性和效率取舍 by Shubheksha 通过Shubheksha 网络通信设计中的一些约束和折衷:摘要 (Some Constraints and Trade-offs In The Des ...

  5. 几何图形在logo设计中的有哪些情感意义?

    作为一名合格的UI设计师,工作中遇到的问题有很多,例如logo设计,是很多UI设计师的一个日常工作之一,小编今天为大家介绍的UI设计培训教程就是几何图形在logo设计中的有哪些情感意义?希望能够帮助到 ...

  6. UI设计培训之设计中的点线面-面

    想要学好UI设计,从事UI设计工作,那么理论基础知识一定要会,今天小编为大家整理的就是关于UI设计中的点线面-面,在平面构成三要素中面是相对占空间最大的元素,在设计中也包含和表现更加强烈的情感色彩,有 ...

  7. 【UI设计培训基础知识】设计中的点线面-线

    UI设计所要学习的知识有很多,想要在后期的工作中稳稳当当,基础知识一定要扎实,下面就是小编为大家整理的一份关于UI设计培训基础知识的相关内容,主要讲的是设计中的点线面-线,来看看下面的详细资料吧. 点 ...

  8. 在UI设计中如何正确使用颜色

    在我们进行UI设计时,颜色往往是我们表达理念重要的一点,但也是我们常常会忽视的一点.颜色其实如同语言一样,我们可以通过颜色的变化组合,来表达不同的情绪. 正确使用颜色不单能让我们吸引到客户,也能更好地 ...

  9. 我翻译的一篇文章,OO设计中对象的创建和使用

    OO设计中对象的创建和使用 转载于:https://www.cnblogs.com/lishu1980/archive/2006/06/22/432526.html

最新文章

  1. 百度二面:一个线程OOM了,其它线程还能运行吗?
  2. simulink和psim仿真结果不同_案例展示金属增材制造过程仿真分析 (下篇)- 微观尺度...
  3. intel——5G的通信网络架构及平台
  4. java代码转置sql数据_SQL Server中的数据科学:数据分析和转换–使用SQL透视和转置
  5. vue项目中vue-router的使用
  6. Eclipse 右键打开文件夹之插件--easy explorer
  7. mycat实例(1)
  8. XEN虚拟机修改系统时间
  9. 看拉扎维《模拟CMOS集成电路设计》的一些总结和思考(一)——绪论
  10. ipad协议传奇820
  11. dns服务器未响应韩国,上海联通DNS
  12. 云南高性能云桌面搭建解决方案、云桌面与传统PC优势对比,云桌面适用场景分析
  13. 实习每日总结_20161220
  14. Proxy SwitchyOmega
  15. 为什么要写博客?写博客有哪些好处?
  16. 吉大c 语言程序设计奥鹏作业,吉大19年9月《C语言程序设计》作业考核试题
  17. winform 下拉框(自定义下拉框控件)
  18. 计算机毕业设计(3)python毕设作品之小说电子书阅读系统
  19. python手机连续点击脚本_Appium-Python 通过 find_element_by_android_uiautomator 后怎么连续点击两次...
  20. 在 2020 秋招中没有取得理想的 offer,可以提前为2021春招做哪些准备?

热门文章

  1. textview 滚动显示.txt
  2. OSGI框架的功能和设计思
  3. 计算机底层书籍三件套--大话计算机
  4. 大型网站核心架构要素--扩展性
  5. DevOps笔记-02:DevOps与微服务之间是什么关系?
  6. MySQL笔记4:desc命令的两个用法
  7. int *p=NULL; *p=9;是错误的!
  8. Zuul Gateway 网关
  9. 【译】混沌工程与区块链
  10. 数据结构之图(2-2)【邻接多重表】适用于无向图