• 发文
  • 评论
  • 微博
  • 空间
  • 微信

C++实现简单的内存池

鲨鱼编程 2024-05-06 11:13 发文

内存池(Memory Pool)是计算机编程中一种重要的内存管理技术,它预先分配一块较大的内存区域,并将其划分为多个大小相等的内存块。这种技术旨在减少因频繁申请和释放小块内存而引发的性能开销。下面,我们将结合代码,一步步讲解如何实现一个简单的内存池,并分析其工作原理。

一、内存池的基本概念

内存池是一种用于动态内存分配的技术,其核心思想是空间换时间。通过预先分配一大块内存,并将其划分为多个小块,内存池能够快速地为程序提供所需的内存,而无需每次都向操作系统申请。这样可以大大减少内存分配和释放的开销,提高程序的运行效率。

二、内存池的实现步骤1. 定义内存池类

首先,我们定义一个名为AdvancedMemoryPool的模板类,它接受一个类型参数T和一个默认大小为100的整数参数PoolSize。这个类将用于管理内存池的分配和回收。

template 

class AdvancedMemoryPool {

    // ...

};

2. 初始化内存池

在类的构造函数中,我们调用expandPool函数来初始化内存池。这个函数将分配一块大小为PoolSize * sizeof(T)的内存,并将其划分为PoolSize个大小为sizeof(T)的内存块。这些内存块的地址被添加到freeChunks_列表中,表示它们是空闲的,可以被分配。

AdvancedMemoryPool() {

    expandPool();

}

private:

void expandPool() {

    char* newBlock = new char[sizeof(T) * PoolSize];

    for (size_t i = 0; i < PoolSize; ++i) {

        freeChunks_.push_back(reinterpret_cast<T*>(newBlock + i * sizeof(T)));

    }

    pool_.push_back(newBlock);

}

3. 分配内存块

alloc函数用于从内存池中分配一个空闲的内存块。它首先检查freeChunks_列表是否为空。如果为空,则调用expandPool函数来扩展内存池。然后,它从freeChunks_列表中取出一个空闲的内存块,并将其从列表中移除。最后,返回这个内存块的地址。

T* alloc() {

    std::lock_guard lock(mutex_); // 确保线程安全

    if (freeChunks_.empty()) {

        expandPool();

    }

    T* ptr = freeChunks_.front();

    freeChunks_.pop_front();

    return ptr;

}

这里使用了std::lock_guard来确保在多线程环境下的线程安全。当多个线程同时尝试分配内存时,std::mutex会确保同一时间只有一个线程能够访问内存池。

4. 回收内存块

dealloc函数用于回收一个之前分配的内存块。它接受一个指向要回收的内存块的指针,并将这个指针添加到freeChunks_列表中,表示这个内存块现在是空闲的,可以被再次分配。

void dealloc(T* ptr) {

    assert(ptr != nullptr); // 确保传入的指针不为空

    std::lock_guard lock(mutex_); // 确保线程安全

    freeChunks_.push_back(ptr);

}

同样,这里也使用了std::lock_guard来确保线程安全。

5. 查询内存池状态

我们还提供了两个函数getFreeChunksCount和getUsedChunksCount来查询内存池的状态。这两个函数分别返回空闲和已使用的内存块数量。

size_t getFreeChunksCount() const {

    std::lock_guard lock(mutex_); // 确保线程安全

    return freeChunks_.size();

}

size_t getUsedChunksCount() const {

    return PoolSize - getFreeChunksCount();

}

三、使用内存池

在主函数中,我们创建了一个AdvancedMemoryPool对象,并使用它来分配和回收内存块。通过调用alloc函数,我们可以从内存池中获取一个空闲的内存块,并使用它来存储数据。当我们不再需要这个内存块时,可以调用dealloc函数将其回收回内存池。

欢迎关注我们的公众号,获取更多有趣、有用的信息和知识!在这里,你可以获取专业的编程知识。快来点击下方关注!微信看文章不方便的朋友也可以点击原文,去我的博客鲨鱼编程 (shayucode.com)查看更多文章。四、完整代码#include   

#include   

#include   

#include   

#include   

  

template   

class AdvancedMemoryPool {  

public:  

    AdvancedMemoryPool() {  

        expandPool();  

    }  

  

    ~AdvancedMemoryPool() {  

        std::lock_guard lock(mutex_);  

        for (auto& chunk : pool_) {  

            delete[] reinterpret_cast<char*>(chunk);  

        }  

    }  

  

    T* alloc() {  

        std::lock_guard lock(mutex_);  

        if (freeChunks_.empty()) {  

            expandPool();  

        }  

  

        T* ptr = freeChunks_.front();  

        freeChunks_.pop_front();  

        return ptr;  

    }  

  

    void dealloc(T* ptr) {  

        assert(ptr != nullptr);  

        std::lock_guard lock(mutex_);  

        freeChunks_.push_back(ptr);  

    }  

  

    size_t getFreeChunksCount() const {  

        std::lock_guard lock(mutex_);  

        return freeChunks_.size();  

    }  

  

    size_t getUsedChunksCount() const {  

        return PoolSize - getFreeChunksCount();  

    }  

  

private:  

    void expandPool() {  

        char* newBlock = new char[sizeof(T) * PoolSize];  

        for (size_t i = 0; i < PoolSize; ++i) {  

            freeChunks_.push_back(reinterpret_cast<T*>(newBlock + i * sizeof(T)));  

        }  

        pool_.push_back(newBlock);  

    }  

  

    mutable std::mutex mutex_;  

    std::list<T*> freeChunks_;  

    std::list<char*> pool_;  

};  

  

// 使用示例  

struct ComplexObject {  

    int data[100];  

    // 假设这是一个复杂的对象,需要动态分配  

};  

  

int main() {  

    AdvancedMemoryPool pool;  

  

    ComplexObject* obj1 = pool.alloc();  

    ComplexObject* obj2 = pool.alloc();  

  

    std::cout << "Free chunks: " << pool.getFreeChunksCount() << std::endl;  

    std::cout << "Used chunks: " << pool.getUsedChunksCount() << std::endl;  

  

    pool.dealloc(obj1);  

    pool.dealloc(obj2);  

  

    std::cout << "Free chunks after deallocation: " << pool.getFreeChunksCount() << std::endl;  

    std::cout << "Used chunks after deallocation: " << pool.getUsedChunksCount() << std::endl;  

  

    return 0;  

}

声明:本文为OFweek维科号作者发布,不代表OFweek维科号立场。如有侵权或其他问题,请及时联系我们举报。
2
评论

评论

    相关阅读

    暂无数据

    鲨鱼编程

    懂点C语言和C++,懂点前沿技术...

    举报文章问题

    ×
    • 营销广告
    • 重复、旧闻
    • 格式问题
    • 低俗
    • 标题夸张
    • 与事实不符
    • 疑似抄袭
    • 我有话要说
    确定 取消

    举报评论问题

    ×
    • 淫秽色情
    • 营销广告
    • 恶意攻击谩骂
    • 我要吐槽
    确定 取消

    用户登录×

    请输入用户名/手机/邮箱

    请输入密码