我的游戏引擎有 2 个分配器:堆和堆栈。
class GameEngine{public:
Allocator* heap; //<-- a custom allocator class
Allocator* stack;
}
今天,我想创建一个需要堆分配器的类Car。
class Car{
MyArray<Car*> nearEnemyCache; //<-- my custom storage, need allocator
};
因此,为了创建汽车实例,我从engine 获取堆分配器并将其分配给car。
class CarFactory{
GameEngine* gameEngine;
Car* createCar(){
Car* car=new Car();
car->nearEnemyCache.setAllocator( gameEngine->heap );
return car;
}
};
这是图表:-
问题
如果 car
类增长并且有很多字段需要分配器:-
class Car{
MyArray<Car*> nearEnemyCache; //<-- need allocator
class A{ };
MyArray<A> as; //<--- need allocator
class B{};
MyUnorderMap<B> bs; //<--- need allocator
};
我将不得不手动为它们分配分配器。
它会导致脏代码。
Car* createCar(){
Car* car=new Car();
car->nearEnemyCache.setAllocator( gameEngine->heap );
car->as.setAllocator( gameEngine->heap );
car->bs.setAllocator( gameEngine->heap ); //<-- so dirty & tedious
return car;
}
我的糟糕解决方案
这两种解决方案都直接或间接地使用全局变量作为默认分配器。
我认为使用全局变量通常是一种不好的做法。
1。全局默认分配器
在程序开始设置全局分配器并作为默认值使用 例如:-
Allocator* defaultAllocator;
template<class T>MyArray{
Allocator* allocator=defaultAllocator;
//... other stuffs
}
int main(){
//create "gameEngine"
defaultAllocator=gameEngine->heap;
// start game
}
2。全局游戏引擎变量。
GameEngine* defaultGameEngine;
template<class T> class MyArray{
Allocator* allocator=defaultGameEngine->heap;
//... other stuffs
}
int main(){
//create "gameEngine"
defaultGameEngine=gameEngine;
// start game
}
类似问题:-
- https://gamedev.stackexchange.com/questions/56025/is-it-acceptable-to-have-a-global-singleton-engine-class-in-an-entity-component : 指出全局变量是坏的。情况和我很相似,但它的替代方案导致了我的问题。
最佳答案
如果您无法想象存在多个堆栈/堆/引擎的情况,那么最好将其表示为单例。
这也可以与您的容器模板化相结合:如果您知道您的汽车将只使用堆分配,那么拥有像 MyArray<Car*, HeapAllocator> nearEnemyCache;
这样的成员将允许容器只访问相应的单例(并将从您的“真实”逻辑中隐藏该部分,因此不会再有脏东西)。
template<class T, class DefaultAlloc = ChosenAtRuntimeAlloc>
class MyArray
{
public:
MyArray() : _allocator(singleton<DefaultAlloc>::get())
{
}
void setAllocator(Allocator* alloc)
{
_allocator = alloc;
}
private:
Allocator* _allocator;
};
如果你愿意,你可以在运行时设置它,但如果你在编译时知道它,就不必这样做。 ChosenAtRuntimeAlloc
当被要求分配时,类只会抛出异常("Must set an allocator at runtime before allocating!"
)。
如果您总是知道您的容器将使用哪些分配器(即您永远不必默认第二个模板参数),那么您甚至可以从您的分配器中删除所有虚函数,而是允许编译器内联所有这些。标准库容器基本上就是这样做的。
关于c++ - 将分配器分配给字段 - 我应该将默认分配器创建为全局变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50737816/