我正在设计一个内存管理容器,考虑到性能和易用性,特别是对于游戏开发项目。这是它的当前状态。
我将从源代码中提取最重要的部分。
// 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)...); }
}
所需的用法是这样的:
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
}
这种延迟插入设计refresh()
具有一些很大的优点:
- 它很快
- 一个实体即使已经死了也可以被“杀死”
- 实体可以从其他实体创建,因为它们不会直接存储在项目中,直到
populate()
被调用
但是,如果不需要继承MemoryManageable
,并且如果有更优雅的删除实体的方法,我会很高兴。
- 有没有办法在内部
MemoryManager
处理alive
bool 而不必继承MemoryManageable
,最重要的是,没有任何性能开销? - 有没有更优雅的方法可以用来删除由 处理的项目
MemoryManager
?
理想情况下,由 处理的项目MemoryManager
应该对此一无所知。
示例用法:在游戏开发中,实体在更新期间被破坏是很常见的。考虑一个具有 int life 成员的“敌人”实体:if(life <= 0) this->destroy();
- 在更新循环期间很容易发生这种情况,如果该实体在销毁时立即从 Manager 中删除,则会导致循环和其他指向死亡的实体出现问题实体。