具体而言,在一个库中,我有一个内存池,它覆盖了某些类的new和delete行为。我希望库的用户能够调用这些类的实例的delete方法,但我需要在稍后的特定清理操作之前保留这些实例。是否可能同时让用户使用常规的new/delete?有没有办法覆盖调用析构函数的默认行为?
具体而言,在一个库中,我有一个内存池,它覆盖了某些类的new和delete行为。我希望库的用户能够调用这些类的实例的delete方法,但我需要在稍后的特定清理操作之前保留这些实例。是否可能同时让用户使用常规的new/delete?有没有办法覆盖调用析构函数的默认行为?
shared_ptr
,而不仅仅是在簿记部分拥有一个shared_ptr
的副本,否则具有weak_ptr
的用户可以使一个应该已经消失并准备进行清理的对象复活。这会使清理代码变得复杂(它需要检查shared_ptr
是否真正唯一,在多线程程序中很难实现),并且意味着OP对这些对象的自定义生命周期对用户可见(他们可以看出对象并没有真正死亡,只是去了一个更好的地方;-) - Jonathan Wakelyshared_ptr
的观点很好,我更新了我的答案。 - Arne Mertz使用智能指针代替new
/delete
(这本身就是一个好的实践)。
使用自定义删除器将对象所有权移动到“等待清理”的对象列表中。
有关智能指针的示例,请参考std::unique_ptr
和std::shared_ptr
。
另一个选项(更加繁琐且更难做到正确性)是只在使用自定义分配器的容器中存储对象,并使分配器的destroy
和deallocate
函数执行“将其移动到待清理暂存区而非实际销毁”部分。我建议选择带有自定义删除器的智能指针方法,而不是分配器方法。
这两个选项(自定义删除器和自定义分配器)都允许您控制对象“销毁”时的确切行为,将对象的实际生命周期结束与用户处理它的时刻分离开来,这无法通过delete
运算符实现。
delete
会运行析构函数。这是每个人都依赖的基本事实。如果你能够禁用析构函数调用(但你不能),那么你将破坏每个人的期望。如果你不希望用户调用析构函数,就不要让析构函数可用。一个受保护的析构函数将使delete
无法调用。
operator delete
是用于内存释放的函数,而delete
操作符则是编译器将其翻译为“析构函数调用和通过operator delete
释放内存”的特殊关键字。因此,重载函数并不会阻止编译器调用析构函数。请注意不改变原意且使内容更加通俗易懂。 - Arne Mertz