我的游戏引擎有2个分配器:堆和堆栈。
class GameEngine{public:
Allocator* heap; //<-- a custom allocator class
Allocator* stack;
}
今天,我想创建一个需要堆分配器的类 Car 。
class Car{
MyArray<Car*> nearEnemyCache; //<-- my custom storage, need allocator
};
因此,要创建汽车实例,我从引擎中抓取堆分配器并将其分配给汽车。
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;
}
两种解决方案都直接或间接使用全局变量作为默认分配器 我认为使用全局变量通常是一种不好的做法。
在程序开头设置全局分配器并将其用作默认值 例如: -
Allocator* defaultAllocator;
template<class T>MyArray{
Allocator* allocator=defaultAllocator;
//... other stuffs
}
int main(){
//create "gameEngine"
defaultAllocator=gameEngine->heap;
// start game
}
GameEngine* defaultGameEngine;
template<class T> class MyArray{
Allocator* allocator=defaultGameEngine->heap;
//... other stuffs
}
int main(){
//create "gameEngine"
defaultGameEngine=gameEngine;
// start game
}
类似问题: -
答案 0 :(得分:1)
如果您无法想象存在多个堆栈/堆/引擎的情况,那么这可能最好表示为单例。
这也可以模板化你的容器:如果你知道你的汽车只会使用堆分配,那么拥有像MyArray<Car*, HeapAllocator> nearEnemyCache;
这样的成员将允许容器只访问相应的单身(并且会将那部分隐藏在你的&#34;真正的&#34;逻辑中,所以那里没有更多的肮脏)。
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!"
类只会抛出异常。
如果始终知道您的容器将使用哪些分配器(即您永远不必默认第二个模板参数),那么您甚至可以从分配器中消除所有虚拟功能,而是允许编译器内联所有这些。这基本上就像标准库容器那样。