内存池(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(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函数将其回收回内存池。
四、完整代码
#include #include #include #include #include template class AdvancedMemoryPool { public: AdvancedMemoryPool() { expandPool(); } ~AdvancedMemoryPool() { std::lock_guard lock(mutex_); for (auto& chunk : pool_) { delete[] reinterpret_cast(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(newBlock + i * sizeof(T))); } pool_.push_back(newBlock); } mutable std::mutex mutex_; std::list freeChunks_; std::list 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; }
#头条创作挑战赛#
热门跟贴