非常简单的问题 - 如何通过分配器为多态对象分配和释放内存?好的,分配内存不是一个大问题:
SomeAllocator::rebind<Child>::other allocator;
Parent*pointer=allocator.allocate(1);
new(pointer) Child;
要解除分配此内存,我应该致电SomeAllocator::rebind<Child>::other::deallocate
...或SomeAllocator::rebind<GrandChild>::other::deallocate
?它是多态对象,我不知道他究竟是什么类型的。所以,我不知道我必须拨打什么分配器。我可以想象一些技巧。例如 - 通过std::allocator<char>().allocate(sizeof(ObjectType))
和std::allocator<char>().deallocate((char*)pointer,sizeof(ObjectType))
分配和释放内存。但是这个伎俩抛弃了任何潜在的优化,例如&#34;这个分配器使用了Child对象池#34;另外,在多态对象中,我不知道这个对象的sizeof。所以,我必须在某处保存这个尺寸。分配实现后已经保存了它(当然,只有99%的情况下,allocate() - 只是重定向到malloc,lol)。它不认为这是非常好的做法。此外,我可以使用虚拟功能,如:
virtual void Child::destroy(){
~Child();
SomeAllocator::rebind<Child>::other().deallocate(this,1);
}
但它也不是很好主意,因为我必须在所有派生类中复制此代码。
那么,为多态对象vis分配器分配和释放内存的最佳决策是什么? PS对不起,如果我的英语不好。
答案 0 :(得分:1)
我会考虑使用概念/模型习语。
该概念定义了公共接口上可用的概念(服务),该模型描述了处理分配器转换和存储的实现。
e.g:
#include <memory>
struct I
{
virtual ~I() = default;
};
struct A : I
{
int x, y, z;
};
struct B : I
{
int a, b, c, x, y, z;
};
template<class T> struct tag {};
struct IPtr
{
struct concept
{
template<class T> void construct(void * addr)
{
ptr_ = new (addr) T ();
}
virtual void dealloc() = 0;
void destroy()
{
ptr_->~I();
dealloc();
}
void* mem_ = nullptr;
I* ptr_ = nullptr;
};
template<class T, class Allocator>
struct model : concept
{
model(Allocator alloc)
: alloc_(alloc)
{
using A2 = typename Allocator::template rebind<T>::other;
auto a2 = A2(alloc_);
mem_ = a2.allocate(1);
ptr_ = new (mem_) T ();
}
virtual void dealloc() override
{
using A2 = typename Allocator::template rebind<T>::other;
auto a2 = A2(alloc_);
a2.deallocate(reinterpret_cast<typename A2::pointer>(mem_), 1);
}
Allocator alloc_;
};
template<class T, class Allocator>
IPtr(tag<T>, Allocator alloc)
: impl_(new model<T, Allocator>(alloc))
{
}
IPtr(IPtr&& r)
: impl_(r.impl_)
{
r.impl_ = nullptr;
}
~IPtr()
{
if (impl_) {
impl_->destroy();
delete impl_;
}
}
private:
concept* impl_;
};
int main()
{
auto alloc = std::allocator<int>();
auto a = IPtr(tag<A>(), alloc);
auto b = IPtr(tag<B>(), alloc);
a;
b;
}