问题描述
当使用内存资源(或分配器)创建对象时,需要在删除时记住它是由哪个内存资源创建的。
将内存资源存储到对象本身并在类的删除操作符中进行适当的删除是一种好的模式吗?下面的代码展示了这个想法:
#include <memory_resource>
using namespace std::pmr;
struct A
{
A (memory_resource * memres_ = nullptr)
: memres(memres_)
{}
memory_resource * memres;
void operator delete(A * this_,std::destroying_delete_t)
{
if ( memory_resource * memres_ = this_->memres )
polymorphic_allocator(memres_).delete_object(this_);
else
::delete(this_);
}
};
int main()
{
A * aGlobal = new A;
delete aGlobal;
memory_resource * memres = get_default_resource();
A * aPmr = polymorphic_allocator(memres).new_object<A>(memres);
delete aPmr;
}
解决方法
一般来说,一个对象的销毁方式应该反映它的创建方式。如果您使用了 new T
,那么您应该使用 delete pT
。如果您从某个资源分配内存,然后使用新的布局,那么您应该调用析构函数并使用该资源释放内存。如果您使用 polymorphic_allocator::new_object
,您应该将其与 polymorphic_allocator::delete_object
一起使用。
是的,这意味着拥有对象(并因此删除它)的代码需要知道如何删除它。但这就是所有权的最终含义。
是的,您可以制作一个知道如何删除自身的对象。但这有点混淆了这个问题。考虑您的用例。如果您传递内存资源,则它可以delete
自身。如果您使用常规 new
,那么它本身可以 delete
。但是,如果您在某些不来自内存资源的内存上使用placement-new
,那么您必须避免在其上调用delete
。这与您分配对象的方式不一致。
简单地说,对象不分配自己的内存,因此也不应该期望它们释放内存。