内存管理容器设计问题 - 项目需要继承

Vit*_*meo 6 c++ memory unique-ptr c++11

我正在设计一个内存管理容器,考虑到性能和易用性,特别是对于游戏开发项目.这是它当前的状态.

我将从源中提取最重要的部分.

// Uptr is a typedef for std::unique_ptr

class MemoryManageable {
    bool alive{true};
    public: bool isAlive() const { return alive; }
};

template<typename T> struct Deleter {
    bool operator()(const Uptr<T>& mItem) const { return !mItem->isAlive(); } 
};  

template<typename T> class MemoryManager {
    // T is the type of items being stored and must inherit MemoryManageable
    std::vector<Uptr<T>> items; 
    std::vector<T*> toAdd; // will be added to items on the next refresh() call
    Deleter<T> deleter;

    void refresh() { 
        items.erase(std::remove_if(std::begin(items), std::end(items), deleter), std::end(items)); 
        for(const auto& i : toAdd) items.push_back(Uptr<T>(i)); toAdd.clear(); 
    }
    void clear() { items.clear(); toAdd.clear(); }

    // Del sets alive to false, so that the item will be deleted and deallocated on the next refresh() call
    void del(T& mItem) { mItem.alive = false; }

    template<typename TType, typename... TArgs> TType& create(TArgs&&... mArgs) { /* creates a new TType* (derived from T) and puts it in toAdd */ }
    template<typename... TArgs> T& create(TArgs&&... mArgs) { return create<T, TArgs...>(std::forward<TArgs>(mArgs)...); }
}
Run Code Online (Sandbox Code Playgroud)

你可以在这里看到真正的用法.

所需的用法是这样的:

struct Entity : public MemoryManageable { 
     Manager& manager; 
     void destroy() { manager.del(*this); } 
     ... 
}

struct Mnnager { 
    MemoryManager<Entity> mm; 
    void del(Entity& mEntity) { mm.del(mEntity); }
    ... 
 }

Manager::update() {
    mm.refresh(); // entities with 'alive == false' are deallocated, and entities in 'mm.toAdd' are added to 'mm.items' 
    for(auto& entity : mm) entity->update(); // entities 'die' here, setting their 'alive' to false 
}
Run Code Online (Sandbox Code Playgroud)

这种延迟插入设计refresh()具有一些很大的优点:

  • 它很快
  • 即使已经死亡,实体也可能被"杀死"
  • 实体可以从其他实体创建,因为它们在populate()被调用之前不会直接存储在项目中

但是,如果不需要继承,我会很高兴MemoryManageable,如果有更优雅的方法来删除实体.

  • 有没有办法MemoryManageralive内部处理bool,而不必继承MemoryManageable,最重要的是,没有任何性能开销?
  • 是否有更优雅的方式可用于删除处理的项目MemoryManager

理想情况下,由他们处理的项目MemoryManager应该对此一无所知.


示例用法:在gamedev中,实体在更新期间被销毁是很常见的.考虑一个带有int life成员的"Enemy"实体:if(life <= 0) this->destroy();- 在更新循环期间很容易发生,如果实体在销毁时立即从Manager中删除,则会导致循环和其他指向死亡的实体出现问题实体.

Vit*_*meo 0

所提供的答案并不令我满意,因此我决定保留所需的继承解决方案。尽管它可能很烦人,但它很有效(没有额外的运行时间成本)并且易于实现/维护。

当前实现:SSVUtils/MemoryManager/MemoryManager.h