如何跟踪对对象的引用?
在仍然需要手动分配内存和指针的世界中(Borland Delphi),我需要一个普遍的解决方案来解决我认为的普遍问题:
在给定的时刻,可以从多个位置(列表,其他对象等)引用一个对象。有没有一种很好的方法来跟踪所有这些引用,以便在对象被销毁时可以对其进行更新?
解决方案
回答
我不太清楚为什么要这么做。我们肯定会在使用它之前在Nil中检查引用吗?
Anwyays,我将考虑两个可能的解决方案:
- 让对象管理器拥有自己的引用计数。
- 创建一个引用计数管理器类。
我可能会将AddRef()和ReleaseRef()函数添加到管理器或者引用感知类。然后,我们可以使用它们检查任何时刻存在多少引用。 COM就是这样。
引用感知类将仅管理其自己的引用计数。管理器可以使用Map将指针与整数进行计数。
回答
我们是要跟踪对象的引用对象,以便在销毁对象时清除这些引用,还是要跟踪何时安全地销毁对象?
如果是后者,那么听起来我们正在寻找垃圾收集器。我从来没有与Delphi打交道,所以我不知道是否有可以使用的GC,但是如果没有,我会感到惊讶。
如果是前者,那么GC可能无济于事。如果Delphi支持OOP /继承(我真的不知道是否支持),则可以执行以下操作(伪代码):
// Anything that will use one of your tracked objects implements this interface interface ITrackedObjectUser { public void objectDestroyed(TrackedObject o); } // All objects you want to track extends this class class TrackedObject { private List<ITrackedObjectUser> users; public void registerRef(ITrackedObjectUser u) { users.add(u); } public void destroy() { foreach(ITrackedObjectUser u in users) { u.objectDestroyed(this); } } }
基本上,每当我们将一个跟踪对象添加到一个集合中时,该集合就会向该对象注册自己。当对象被销毁时(我想我们会在对象的析构函数中调用destroy()),然后该对象会向集合发出信号,表明该对象已被销毁,因此该集合可以执行所需的任何操作。
不幸的是,如果我们要使用内置集合,这并不是一个很好的解决方案。我们必须编写自己的集合对象(尽管它们可以只包装内置对象)。而且,这需要确保我们要在要跟踪该对象的任何地方进行注册。这不是我认为的"快乐"解决方案,尽管对于小型项目而言,它可能还不错。我主要希望这个想法将有助于产生其他想法。 :)
回答
如果要通知其他人更改,则应实施"观察者模式"。 Delphi已经为TComponent后代为我们完成了此任务。我们可以调用TComponent.FreeNotification方法,并在销毁其他组件时通知对象。它通过调用Notification方法来实现。我们可以通过调用TComponent.RemoveFreeNotification从通知列表中删除自己。另请参阅此页面。
大多数垃圾收集器不允许我们获取参考列表,因此在这种情况下它们将无济于事。如果我们要使用接口,Delphi可以进行引用计数,但是再次需要我们自己跟踪引用。
回答
我们是否有特定原因想要这个?我们是否在流氓指针方面遇到问题,或者我们有一天认为这可能是一个问题?
恕我直言,如果我们正确设计应用程序就不会有问题,使用适当的模式确实会对我们有所帮助。
有关模式的一些信息:
http://delphi.about.com/od/oopindelphi/a/aa010201a.htm
http://www.obsof.com/delphi_tips/pattern.html