题:
有没有什么办法让删除的行为就像一个虚拟的,即所谓的当奈何?
为什么我需要的答案:
我使用的是自定义的内存池从内存中释放所有对象时的静态方法被称为Pool::freeAllObjects()
所有的类都有一个重载的operator new如下所示:
void * operator new (size_t size)
{
void * obj = Pool::memory()->allocate(size);
Pool::memory()->save_destructor((ClassName*)obj);
return obj;
}
Pool::memory()->save_destructor()
只是保存一个指向运行泛型类型的析构函数。
如果没有人要求delete
对与池创建的对象则一切正常行为,但在代码中,我们想用它存在具有对象的许多情况下delete
要求,所以向后兼容性我试图让一个重载delete
像这样
void operator delete(void*) {/*do nothing*/}
在已经超载的类new
使用Pool::memory()
但它看起来像没有解决不了的问题。 我用一个简单的std ::法院看到利弊/析构函数调用,一个重载的删除,如:
void operator delete(void*) {std::cout << "deleting ClassName" << std::endl;}
所以在这样的代码:
ClassName * instance = new ClassName();
instance->runMethod();
delete instance; //this is legacy code calling delete before the pool was developed
/*
other code goes here
*/
Pool::freeAllObjects(); // oops instance was already deleted
我得到以下的输出:
constructing ClassName
< -调用的构造函数
destructing ClassName
< -析构函数调用,因为调用删除
deleting ClassName
< -删除显示它的消息
destructing ClassName
< -析构函数调用,因为池的:: freeAllObjects运行析构函数的对象
编辑:对不起,我没有提到的要求是:不要使用智能指针和制作运营商删除私人(我认为这是由方式的最佳选择),也不允许。
你不能阻止delete
从调用析构函数; 这就是它的作用。 但因为你是追赶operator delete
功能稍后调用,您可以使用某种隐藏的标志。 就像是:
union MemoryHeader
{
bool hasBeenDeleted;
double forAlignment;
};
void* operator new ( size_t size )
{
MemoryHeader* hdr = static_cast<MemoryHeader*>(
Pool::memory()->allocate( size + sizeof( MemoryHeader ) ) );
hdr->hasBeenDeleted = false;
void* obj = hdr + 1;
Pool::memory()->save_destructor( (ClassName*)hdr );
return obj;
}
void operator delete( void* obj )
{
MemoryHeader* hdr = static_cast<MemoryHeader*>( obj ) - 1;
hdr->hasBeenDeleted = true;
}
然后,当你运行你删除器,可以检查该标志。
或者甚至更好,你的情况; 在operator delete
功能,只需注销析构函数的对象:添加clear_destructor
功能什么Pool::memory()
返回,并调用它。
operator delete
是一个释放的功能 。
一个删除表达式首先调用析构函数,那么相关的释放功能。
“池::内存() - > save_destructor()只是保存一个指向运行泛型类型的析构函数。” 为解精设计。 相反,如果释放的责任就是要共享,然后处理,在用更高层次std::shared_ptr
(你可以限制你的类只能通过产生一个函数来实例化std::shared_ptr
)。 这就是std::shared_ptr
是。
与负责销毁对象分配器,高低电平担忧混为一谈,导致复杂性和可能的错误。
随着这些问题分开,例如使用std::shared_ptr
,你会得到一个更简单,更可靠的设计,这也将是更符合在C ++语言这样的分离。
经典的著作“现代C ++设计”由安德烈Alexandrescu的详细讨论如何实现自定义的分配方案。 有机会,你可以找到在洛基库分配器。 我认为,它是开源的。
如果你想有一个类似Java的自动垃圾回收,那么你可能能够使用贝姆收集器。 我知道有些人已经成功地用它在中型至大型项目。 但是,我没有直接经验,但检查出来,如果这就是你的目标是什么了。
如果你想避免被析构函数自动调用你必须实现placement new
运营商,如果其中的析构函数必须显式调用(指C ++ FAQ )。
如果你想通过禁用释放内存delete
声明,超载是一个好主意,无论是全球范围内(如果你知道你在做什么)或每类(使用继承可能。 new
/ delete
运营商都继承)。
这一切都取决于你想要达到什么目的,你必须承受什么兼容现有系统。
无论哪种方式 - 这是做-能。 另一个问题是 - 是的方式,它应该做的事。
你可能会考虑另一种方法是使用禁用的delete
了相关的类。
只是让析构函数protected
或private
,并添加池分配器的friend
。
这加强了而不是支持任何不正确的使用 (另外一个答案)加入更多的复杂性,或改变设计的东西更简单和干净(我的其他答案) 现有的设计 。