我目前正在开发一个用c ++编写的游戏。因为没有垃圾收集器,所以总是要小心地删除对象,并确保删除后不再访问这些对象。
现在随着项目的发展,一些对象可能会被越来越多的地方引用。例如,游戏中的我的单元可以从渲染器,场景层次结构,选择机制,HUD等引用。现在 - 如果一个对象被删除,则必须确保引用该对象的所有其他类都将被通知
或者让我们说另一种方式 - 如果我创建一个可以引用我的单位的新类,我还必须更改单元的代码(或单元管理器或任何模块删除单元的代码,如果它得到为了确保这个新模块知道它当前引用的特定单元何时被删除。
现在我认为有一个简单的事件驱动的通用方法可以通过创建另一个对象可以订阅的基类来解决这个问题。像这样:
class DeletableBase;//forward declaration
class ISubscriber{
public:
virtual someObjectGotDeleted(DeletableBase* deletedObject)=0;
};
class DeletableBase{
private:
vector<ISubscriber*> subscribers;
public:
virtual ~DeletableBase(){
for(int i=0; i<subscribers.size(); i++)
subscribers[i]->someObjectGotDeleted(this);
}
subscribeForDeleteEvent(ISubscriber* subscriber){
subscribers.push_back(subscriber);
}
};
有了 - 如果我从一个新类引用从这个类继承的任何对象,我可以简单地将自己添加为订阅者,如果该对象将从任何其他地方删除,我会得到关于它的通知。
这是一种“干净”的编码方式吗?
答案 0 :(得分:6)
如果这纯粹是关于内存管理(而不是状态更改),请改用智能指针。从shared_ptr
开始,然后使用make_shared
/ allocate_shared
或boost::intrusive_ptr
进行优化,如果速度太慢。
答案 1 :(得分:1)
你必须考虑的一件事(特别是如果你正在编写一个游戏)是当你的一个订阅对象在主线程上被删除时,你的游戏很可能会阻塞,直到每个订阅者都完成了删除对象时要做的事情。如果你不小心,这可能会影响游戏性能。
答案 2 :(得分:0)
您必须避免丢弃其他对象引用的对象,而不是相反。 Boost smart pointers将为您完成90%的工作。
P.S。:C ++有一个垃圾收集器: - )
答案 3 :(得分:0)
恕我直言,你需要实现自己的内存分配器。您可以观察释放的内存以了解实例类型或类,而不是观察每个实例。当然,为此,您的内存分配器应该是可观察的。您可以使用map
或set
之类的数据结构或multi
版本来更有效地通知观察者。这意味着,您的记忆管理员将是中介以及可观察。
此外,如果这些释放或通知操作彼此独立,您可以使用命令模式来分隔执行和线程上下文。希望这会有所帮助。