內(nèi)存池(Memory Pool)是計(jì)算機(jī)編程中一種重要的內(nèi)存管理技術(shù),它預(yù)先分配一塊較大的內(nèi)存區(qū)域,并將其劃分為多個(gè)大小相等的內(nèi)存塊。這種技術(shù)旨在減少因頻繁申請(qǐng)和釋放小塊內(nèi)存而引發(fā)的性能開(kāi)銷。下面,我們將結(jié)合代碼,一步步講解如何實(shí)現(xiàn)一個(gè)簡(jiǎn)單的內(nèi)存池,并分析其工作原理。
內(nèi)存池是一種用于動(dòng)態(tài)內(nèi)存分配的技術(shù),其核心思想是空間換時(shí)間。通過(guò)預(yù)先分配一大塊內(nèi)存,并將其劃分為多個(gè)小塊,內(nèi)存池能夠快速地為程序提供所需的內(nèi)存,而無(wú)需每次都向操作系統(tǒng)申請(qǐng)。這樣可以大大減少內(nèi)存分配和釋放的開(kāi)銷,提高程序的運(yùn)行效率。
首先,我們定義一個(gè)名為AdvancedMemoryPool的模板類,它接受一個(gè)類型參數(shù)T和一個(gè)默認(rèn)大小為100的整數(shù)參數(shù)PoolSize。這個(gè)類將用于管理內(nèi)存池的分配和回收。
template <typename T, size_t PoolSize = 100>class AdvancedMemoryPool { // ...};
在類的構(gòu)造函數(shù)中,我們調(diào)用expandPool函數(shù)來(lái)初始化內(nèi)存池。這個(gè)函數(shù)將分配一塊大小為PoolSize * sizeof(T)的內(nèi)存,并將其劃分為PoolSize個(gè)大小為sizeof(T)的內(nèi)存塊。這些內(nèi)存塊的地址被添加到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函數(shù)用于從內(nèi)存池中分配一個(gè)空閑的內(nèi)存塊。它首先檢查freeChunks_列表是否為空。如果為空,則調(diào)用expandPool函數(shù)來(lái)擴(kuò)展內(nèi)存池。然后,它從freeChunks_列表中取出一個(gè)空閑的內(nèi)存塊,并將其從列表中移除。最后,返回這個(gè)內(nèi)存塊的地址。
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來(lái)確保在多線程環(huán)境下的線程安全。當(dāng)多個(gè)線程同時(shí)嘗試分配內(nèi)存時(shí),std::mutex會(huì)確保同一時(shí)間只有一個(gè)線程能夠訪問(wèn)內(nèi)存池。
dealloc函數(shù)用于回收一個(gè)之前分配的內(nèi)存塊。它接受一個(gè)指向要回收的內(nèi)存塊的指針,并將這個(gè)指針添加到freeChunks_列表中,表示這個(gè)內(nèi)存塊現(xiàn)在是空閑的,可以被再次分配。
void dealloc(T* ptr) { assert(ptr != nullptr); // 確保傳入的指針不為空 std::lock_guard<std::mutex> lock(mutex_); // 確保線程安全 freeChunks_.push_back(ptr);}
同樣,這里也使用了std::lock_guard來(lái)確保線程安全。
我們還提供了兩個(gè)函數(shù)getFreeChunksCount和getUsedChunksCount來(lái)查詢內(nèi)存池的狀態(tài)。這兩個(gè)函數(shù)分別返回空閑和已使用的內(nèi)存塊數(shù)量。
size_t getFreeChunksCount() const { std::lock_guard<std::mutex> lock(mutex_); // 確保線程安全 return freeChunks_.size();}size_t getUsedChunksCount() const { return PoolSize - getFreeChunksCount();}
在主函數(shù)中,我們創(chuàng)建了一個(gè)AdvancedMemoryPool對(duì)象,并使用它來(lái)分配和回收內(nèi)存塊。通過(guò)調(diào)用alloc函數(shù),我們可以從內(nèi)存池中獲取一個(gè)空閑的內(nèi)存塊,并使用它來(lái)存儲(chǔ)數(shù)據(jù)。當(dāng)我們不再需要這個(gè)內(nèi)存塊時(shí),可以調(diào)用dealloc函數(shù)將其回收回內(nèi)存池。
#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]; // 假設(shè)這是一個(gè)復(fù)雜的對(duì)象,需要?jiǎng)討B(tài)分配 }; 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++實(shí)現(xiàn)簡(jiǎn)單的內(nèi)存池
聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。郵件:2376512515@qq.com