设计一个只能由特定类实例化的类(如果可能的话,通过make_unique)
Design a class that could only be instantiated by a specific class(by make_unique if possible)
我正在实现一个幼稚的内存池,在我的实现中有两个类。
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;
};
谢谢你的链接。我知道如何使用私有ctor启用make_unique。然而,我想知道是否有更好的方式来实现我的愿望。
另外,我对operator new
和operator delete
的用法正确吗?
有点偏离主题,但MemoryBlock
没有理由知道类型T
。
在您的实现中,当您创建一个MemoryBlock
然后销毁它时,它最终会调用从未构造过的对象的析构函数,这是未定义的行为。
MemoryBlock
应该只知道对象的大小和块中对象的数量。
相关文章:
- std::map<struct,struct>::find 找不到匹配项,但是如果我循环通过 begin() 到 end(),我在那里看到匹配项
- 设计一个只能由特定类实例化的类(如果可能的话,通过make_unique)
- 如果我们通过引用传递变量,则递归中使用的堆栈空间量是否为零?
- 为什么 WinInet 在通过 FQDN 连接时无法通过协商自动进行身份验证,但如果通过 IP 连接则成功?
- 如果 C 函数仍然可以间接执行(通过回调函数),那么将它声明为静态函数是否是一种不好的做法?
- 我如何在一个 if 语句中声明所有数字我尝试通过其他方式声明所有数字,如果一个接一个,但似乎代码有逻辑错误
- 如果我想通过OpenCV dnn模块加载PyTorch的模型,我应该如何保存它
- 如果字符串在 C/C++ 中没有 NUL 字符(以防编译器允许它通过)会发生什么情况?
- 如果我们没有在 C++ 中传递大小变量,则通过函数查找数组的大小
- 如果通过委托给“malloc”的重载“new[]”分配,“释放”内存是否安全
- 这个问题叫什么?如果通过基类型传递结构,则后代类型中的字段在方法中不可用
- 如果通过按钮或时间更改执行,Maya API 的行为会有所不同
- 如果通过循环求和,下面的程序会找到正确的答案,但如果通过GP的公式求和,则会找到不正确的答案.为什么
- 如果通过指针分配,C++ vector.size() 不会更新
- 如果通过代理连接,客户端不会断开连接
- 如果通过引用捕获异常,可以修改它并重新抛出吗?
- 如果通过单击任务栏按钮最小化程序,SW_SHOWNOACTIVATE不起作用
- 如果通过模板函数中的 const 引用传递,数组不会衰减到指针
- 如果通过函数传递,右值引用是否优化
- 如果通过指针访问这个函数,为什么会导致访问冲突?