我正在实现一个朴素的内存池,我的实现中有两个类。
FixedMemoryPool<T>
和MemoryBlock<T>
FixedMemoryPool
为newElement
之类的用户提供接口,并通过MemoryBlock
管理内存。
很明显,没有用户可以访问MemoryBlock
,它的生命周期完全由FixedMemoryPool管理。对于每个MemoryBlock<T>
,只能由FixedMemoryPool<T>
创建。
这是我的实现方式。
template
<typename T>
class FixedMemoryPool;
template<typename T>
class MemoryBlock
{
friend class FixedMemoryPool<T>;
using blockPtr = unique_ptr<MemoryBlock<T>>;
struct _ConstructorTag { explicit _ConstructorTag() = default; };
public:
MemoryBlock(size_t blockSize, _ConstructorTag)
:data(reinterpret_cast<T*>(operator new(sizeof(T) * blockSize))), allocatedCounter(0), next(nullptr)
{
}
~MemoryBlock()
{
for (size_t i = 0; i != allocatedCounter; i++) {
(data + i) -> ~T();
}
operator delete(data);
}
private:
T* data;
size_t allocatedCounter;
blockPtr next;
template
<typename... Args>
T* construct(Args&&... args)
{
return new (data + (allocatedCounter++)) T(std::forward<Args>(args)...);
}
MemoryBlock(const MemoryBlock&) = delete;
MemoryBlock& operator=(const MemoryBlock&) = delete;
};
template
<typename T>
class FixedMemoryPool
{
public:
using valueType = T;
FixedMemoryPool(size_t blockSize = 64)
:blockSize(blockSize), head(make_unique<MemoryBlock<T>>(blockSize, MemoryBlock<T>::_ConstructorTag{}))
{
}
FixedMemoryPool(const FixedMemoryPool&) = delete;
FixedMemoryPool& operator=(const FixedMemoryPool&) = delete;
FixedMemoryPool(FixedMemoryPool&& pool) = delete;
FixedMemoryPool& operator=(FixedMemoryPool&&) = delete;
template
<typename... Args>
T* newElement(Args&&... args)
{
//...
}
~FixedMemoryPool() = default;
private:
void expand()
{
// ...
}
size_t blockSize;
unique_ptr<MemoryBlock<T>> head;
};
感谢link。我知道如何使用私有ctor启用make_unique。 但是,我想知道是否有更好的方法可以满足我的愿望。
我对operator new
和operator delete
的用法正确吗?
答案 0 :(得分:1)
有点题外话,但MemoryBlock
没有理由知道类型T
。
在实现中,创建MemoryBlock
然后销毁它时,它最终会调用从未构造的对象的析构函数,这是未定义的行为。
MemoryBlock
仅应了解块中的对象大小和对象数。