5

我目前正在使用 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);
    }
};

有了这个 - 如果我从一个新类引用从这个类继承的任何对象,我可以简单地将自己添加为订阅者,如果该对象将从任何其他地方删除,我将收到有关它的通知。

这是一种“干净”的编码方式吗?

4

4 回答 4

6

如果这纯粹是关于内存管理(而不是状态更改),请改用智能指针。从 开始shared_ptr,然后使用make_shared/进行优化,allocate_shared或者boost::intrusive_ptr如果它太慢。

于 2011-02-02T14:53:24.967 回答
1

您必须考虑的一件事(特别是如果您正在编写游戏)是,当您的订阅对象之一在主线程上被删除时,您的游戏很可能会阻塞,直到它的每个订阅者都完成了它正在做的事情在删除对象时执行。如果您不小心,这可能会影响游戏性能。

于 2011-02-02T14:53:46.680 回答
0

您必须避免丢弃其他对象引用的对象,但不能反过来。Boost 智能指针将为您完成 90% 的工作。

PS:C++ 有一个垃圾收集器 :-)

于 2011-02-02T15:04:56.783 回答
0

恕我直言,您需要实现自己的内存分配器。您可以观察释放的内存,而不是观察每个实例,以了解实例类型或类。当然,为此,您的内存分配器应该是可观察的。您可以使用mapset喜欢数据结构或multi它们的版本来更有效地通知观察者。这意味着,您的内存管理器将是一个调解器,也是可观察的。

另外,如果这些释放或通知动作是相互独立的,您可以使用命令模式来分离执行和线程上下文。希望这可以帮助。

于 2011-02-02T15:27:25.227 回答