推荐答案
// www.javascriptcn.com code example
#include <iostream>
#include <vector>
class MemoryPool {
public:
MemoryPool(size_t blockSize, size_t blockCount)
: blockSize_(blockSize), blockCount_(blockCount) {
pool_.resize(blockCount_ * blockSize_);
freeBlocks_.resize(blockCount_);
for (size_t i = 0; i < blockCount_; ++i) {
freeBlocks_[i] = &pool_[i * blockSize_];
}
}
void* allocate() {
if (freeBlocks_.empty()) {
throw std::bad_alloc();
}
void* block = freeBlocks_.back();
freeBlocks_.pop_back();
return block;
}
void deallocate(void* block) {
freeBlocks_.push_back(static_cast<char*>(block));
}
private:
size_t blockSize_;
size_t blockCount_;
std::vector<char> pool_;
std::vector<void*> freeBlocks_;
};
int main() {
MemoryPool pool(sizeof(int), 10);
int* p1 = static_cast<int*>(pool.allocate());
*p1 = 42;
std::cout << *p1 << std::endl;
pool.deallocate(p1);
return 0;
}本题详细解读
1. 内存池的基本概念
内存池是一种内存管理技术,它预先分配一大块内存,然后在程序运行期间从这块内存中分配和释放小块内存。内存池的主要目的是减少频繁的内存分配和释放操作,从而提高程序的性能。
2. 实现思路
- 预分配内存:在内存池初始化时,预先分配一大块内存,这块内存将被划分为多个大小相等的块。
- 管理空闲块:使用一个数组或链表来记录哪些内存块是空闲的,哪些已经被分配。
- 分配内存:当需要分配内存时,从空闲块列表中取出一个块并返回其地址。
- 释放内存:当内存不再需要时,将其返回到空闲块列表中。
3. 代码解析
- MemoryPool类:该类封装了内存池的实现。构造函数接受两个参数:
blockSize表示每个内存块的大小,blockCount表示内存池中内存块的数量。 - allocate方法:从空闲块列表中取出一个块并返回其地址。如果空闲块列表为空,则抛出
std::bad_alloc异常。 - deallocate方法:将释放的内存块返回到空闲块列表中。
- pool_:这是一个
std::vector<char>,用于存储预分配的内存块。 - freeBlocks_:这是一个
std::vector<void*>,用于存储空闲内存块的指针。
4. 使用示例
在main函数中,我们创建了一个MemoryPool对象,并分配了一个int大小的内存块。然后我们使用这个内存块存储一个整数值,并打印出来。最后,我们将这个内存块释放回内存池。
5. 注意事项
- 线程安全:上述实现是单线程的,如果在多线程环境中使用,需要添加适当的同步机制。
- 内存对齐:在实际应用中,可能需要考虑内存对齐问题,以提高访问效率。
- 扩展性:如果内存池中的内存块用尽,可以考虑动态扩展内存池的大小。