• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >编程问答 > union使用在空闲链表里如何节省空间?

union使用在空闲链表里如何节省空间?

作者:佚名 字体:[增加 减小] 来源:互联网 时间:2017-06-07

佚名通过本文主要向大家介绍了空闲链表,空闲链表法,空闲块链表,union-click jd,日本union电机等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
问题:union使用在空闲链表里如何节省空间?
描述:

我在阅读《STL源码剖析》中看到关于内存组织成空闲链表的结构:

union obj{
    union obj* next;
    char client_data[1];
};

使用union主要是为了节省空间,当我们以一个指针得到该块内存时,可以完全使用该块内存。假如我们用result*得到该块内存后,请问我们应该如何根据client_data来存储数据呢?


解决方案1:

client_data是C/C++常见的变长数组实现方式,如果编译器支持0长度的数组,还可以申明为client_data[0]达到更节省的目的(非标准,这里client_data[1]具有广泛的兼容性)。

由于节省了内存,union obj的大小也就一个指针大小(next指针的大小)。

EDIT: 之前犯了严重的错误,写成了对应struct的了。。。

分配内存的时候,直接分配一块内存给obj即可,一般是8的倍数(因为内存对齐等因素):

obj * block = (obj *)malloc(128); // 分配一块128字节的内存
free_list_ptr->next = block; // 挂接到free_list上

由于这个是free_list用于分配内存的,就有两个作用,一个是指向下一块空白内存(当存在与free_list中时),一个就是供用户使用的一块内存(不存在于free_list)。

当在free_list中时,不要担心next指针与用户数据重叠,因为该块内存会从free_list中取出:

// detach
obj * block = free_list_ptr->next;
free_list_ptr->next = NULL;
// 使用这块内存(block, 128字节)

这里补一个简单的例子,固定大小的内存池(每次只能取一整块,每块大小固定)

// g++ -std=c++11
#include <cstdio>
#include <new>
#include <vector>

using std::size_t;
using std::vector;
using std::bad_alloc;

// 固定大小内存池, 非常基本的演示
template<size_t _BLOCK_SIZE = 64, size_t _NUM_BLOCKS = 16>
class fixed_mem_pool
{
    union obj
    {
        union obj *next;
        char client_data[1];
    };

public:
    enum
    {
        BLOCK_SIZE = _BLOCK_SIZE,
        NUM_BLOCKS = _NUM_BLOCKS
    };

public:
    fixed_mem_pool()
    {
        // 连续分配一块内存, 初始化时分成`NUM_BLOCKS`份
        chunks_ = new char[BLOCK_SIZE * NUM_BLOCKS];

        free_list_head_ = reinterpret_cast<obj *>(chunks_);
        auto cur_obj = free_list_head_;
        auto next_block_ptr = free_list_head_->client_data + BLOCK_SIZE;

        // 构建free_list(链表), 标记可用内存
        for (auto i = 1; i < NUM_BLOCKS; i++)
        {
            cur_obj->next = reinterpret_cast<obj *>(next_block_ptr);
            cur_obj = cur_obj->next;
            next_block_ptr += BLOCK_SIZE;
        }

        cur_obj->next = nullptr;
    }

    ~fixed_mem_pool()
    {
        delete chunks_;
    }

    void *allocate()
    {
        if (free_list_head_ == nullptr)
        {
            throw bad_alloc();
        }

        // Take block from head directy.
        void *p = free_list_head_;
        free_list_head_ = free_list_head_->next;
        // Remember, The size of this block is `BLOCK_SIZE`.
        return p;
    }

    void free(void *p)
    {
        // Return ptr back to free list
        auto head = reinterpret_cast<obj *>(p);
        head->next = free_list_head_;
        free_list_head_ = head;
    }

    // print free list strucutre
    void diagnose()
    {
        printf("----------------------------------\n");
        printf("Blocks: %4d, block size: %4d\n", blocks(), block_size());
        auto p = free_list_head_;
        while (p != nullptr)
        {
            printf("free block @ %p\n", p);
            p = p->next;
        }
        printf("----------------------------------\n");
    }

    inline size_t blocks() const
    {
        return NUM_BLOCKS;
    }

    inline size_t block_size() const
    {
        return BLOCK_SIZE;
    }

private:
    char *chunks_;
    obj *free_list_head_;
};


int main()
{
    // Create a memory pool, with 4 blocks, each block size is 64.
    fixed_mem_pool<64, 4> mempool;
    mempool.diagnose();

    vector<char *> blocks;

    for (auto i = 0; i < mempool.blocks(); i++)
    {
        char *p = reinterpret_cast<char *>(mempool.allocate());
        blocks.push_back(p);
        printf("Got a free block, addr @ %p\n", p);
    }

    try
    {
        // Will bad_alloc because no free block in mempool
        mempool.allocate();
    }
    catch (bad_alloc &)
    {
        printf("Allocated %u memory blocks, each of size %u\n", blocks.size(), mempool.block_size());
    }

    // Use the blocks, this is just a naive demonstration...
    for (auto i = 0; i < blocks.size(); i++)
    {
        snprintf(blocks[i], mempool.block_size(), "This is allocated block #%d.\n", i + 1);
    }

    // Return all blocks back
    for (auto block : blocks)
    {
        mempool.free(block);
    }
    blocks.clear();

    return 0;
}


分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • union使用在空闲链表里如何节省空间?

相关文章

  • 2017-06-07 IntelRCoreTM2Duocpue7500@是Pentium4处理吗?
  • 2017-06-07 如何爬取百度指数的数据?
  • 2017-06-07 七牛上传图片:unsupportedformat:image:unknownformat
  • 2017-06-07 [golang开源]Docker是dotCloud最近几个月刚宣布的开源引擎
  • 2017-06-07 go语言类型转换
  • 2017-06-07 正则表达式中/\b\b/出现空字符串个数问题
  • 2017-06-07 ruby/grape问题
  • 2017-06-07 如何设置空间的主页和404页面
  • 2017-06-07 如何用Jboss搭建SOA应用系统?
  • 2017-06-07 (python)如何kill掉后台中的tail-f

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 求任意进制转换的高效算法
    • jbosstools插件的问题
    • qiniudncom/域名解析挂掉了
    • python爬虫开发出现问题failedtoretrieveALPNresult该如何处理
    • python27urllib2获取网页显示不全
    • python线程sleep进程也被阻塞了
    • (python)pyinstaller打包成单独exe
    • python多组合分组排序问题
    • qrsync/log过于巨大无法快速进入同步上传
    • java中的orm框架

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有