內存池(Memory Pool)是計算機編程中一種重要的內存管理技術,它預先分配一塊較大的內存區域,并將其劃分為多個大小相等的內存塊。這種技術旨在減少因頻繁申請和釋放小塊內存而引發的性能開銷。下面,我們將結合代碼,一步步講解如何實現一個簡單的內存池,并分析其工作原理。
內存池是一種用于動態內存分配的技術,其核心思想是空間換時間。通過預先分配一大塊內存,并將其劃分為多個小塊,內存池能夠快速地為程序提供所需的內存,而無需每次都向操作系統申請。這樣可以大大減少內存分配和釋放的開銷,提高程序的運行效率。
首先,我們定義一個名為AdvancedMemoryPool的模板類,它接受一個類型參數T和一個默認大小為100的整數參數PoolSize。這個類將用于管理內存池的分配和回收。
template <typename T, size_t PoolSize = 100>class AdvancedMemoryPool { // ...};
在類的構造函數中,我們調用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);}
alloc函數用于從內存池中分配一個空閑的內存塊。它首先檢查freeChunks_列表是否為空。如果為空,則調用expandPool函數來擴展內存池。然后,它從freeChunks_列表中取出一個空閑的內存塊,并將其從列表中移除。最后,返回這個內存塊的地址。
T* alloc() { std::lock_guard<std::mutex> lock(mutex_); // 確保線程安全 if (freeChunks_.empty()) { expandPool(); } T* ptr = freeChunks_.front(); freeChunks_.pop_front(); return ptr;}
這里使用了std::lock_guard來確保在多線程環境下的線程安全。當多個線程同時嘗試分配內存時,std::mutex會確保同一時間只有一個線程能夠訪問內存池。
dealloc函數用于回收一個之前分配的內存塊。它接受一個指向要回收的內存塊的指針,并將這個指針添加到freeChunks_列表中,表示這個內存塊現在是空閑的,可以被再次分配。
void dealloc(T* ptr) { assert(ptr != nullptr); // 確保傳入的指針不為空 std::lock_guard<std::mutex> lock(mutex_); // 確保線程安全 freeChunks_.push_back(ptr);}
同樣,這里也使用了std::lock_guard來確保線程安全。
我們還提供了兩個函數getFreeChunksCount和getUsedChunksCount來查詢內存池的狀態。這兩個函數分別返回空閑和已使用的內存塊數量。
size_t getFreeChunksCount() const { std::lock_guard<std::mutex> lock(mutex_); // 確保線程安全 return freeChunks_.size();}size_t getUsedChunksCount() const { return PoolSize - getFreeChunksCount();}
在主函數中,我們創建了一個AdvancedMemoryPool對象,并使用它來分配和回收內存塊。通過調用alloc函數,我們可以從內存池中獲取一個空閑的內存塊,并使用它來存儲數據。當我們不再需要這個內存塊時,可以調用dealloc函數將其回收回內存池。
#include <iostream> #include <list> #include <mutex> #include <cassert> #include <cstdlib> template <typename T, size_t PoolSize = 100> class AdvancedMemoryPool { public: AdvancedMemoryPool() { expandPool(); } ~AdvancedMemoryPool() { std::lock_guard<std::mutex> lock(mutex_); for (auto& chunk : pool_) { delete[] reinterpret_cast<char*>(chunk); } } T* alloc() { std::lock_guard<std::mutex> 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<std::mutex> lock(mutex_); freeChunks_.push_back(ptr); } size_t getFreeChunksCount() const { std::lock_guard<std::mutex> 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<ComplexObject> 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; }
本文鏈接:http://www.tebozhan.com/showinfo-26-86997-0.html如何用C++實現簡單的內存池
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com