C++ 将分配器分配给字段-是否应将默认分配器创建为全局变量?
我的游戏引擎有两个分配器:堆和堆栈C++ 将分配器分配给字段-是否应将默认分配器创建为全局变量?,c++,singleton,c++14,allocator,C++,Singleton,C++14,Allocator,我的游戏引擎有两个分配器:堆和堆栈 class GameEngine{public: Allocator* heap; //<-- a custom allocator class Allocator* stack; } 图如下:- 问题 如果car类增长,并且有很多字段需要分配器:- class Car{ MyArray<Car*> nearEnemyCache; //<-- need allocator class A{ }
class GameEngine{public:
Allocator* heap; //<-- a custom allocator class
Allocator* stack;
}
图如下:-
问题
如果car
类增长,并且有很多字段需要分配器:-
class Car{
MyArray<Car*> nearEnemyCache; //<-- need allocator
class A{ };
MyArray<A> as; //<--- need allocator
class B{};
MyUnorderMap<B> bs; //<--- need allocator
};
等级车{
MyArray nearEnemyCache;//如果您无法想象存在多个堆栈/堆/引擎的情况,那么最好将其表示为单例
这也可以与模板化容器相匹配:如果您知道您的汽车只会使用堆分配,那么在nearEnemyCache附近有一个成员,如MyArray;
将允许容器只访问相应的单例(并且将从您的“真实”逻辑中隐藏该部分,这样就不会再脏了)
模板
类MyArray
{
公众:
MyArray():分配程序(singleton::get())
{
}
void setAllocator(分配器*alloc)
{
_分配器=alloc;
}
私人:
分配器*\u分配器;
};
然后,如果您愿意,可以在运行时设置它,但如果您在编译时知道它,则不必这样做。ChosenAtRuntimeAlloc
类在被要求分配时只会抛出一个异常(“必须在运行时设置一个分配器,然后再分配!”
)
如果您始终知道容器将使用哪些分配器(即,您永远不必默认使用第二个模板参数)然后,您甚至可以从分配器中删除所有虚拟函数,而允许编译器内联所有这些函数。这基本上就是标准库容器的工作方式。您推出自己的容器而不使用std::
实用程序有什么原因吗?可以用于研究目的。@DeiDei在一些测试中说在游戏中,我发现我的略快于std:
。分配器真的是在运行时确定的吗?模板化容器(以及使用它们的类)在分配器类型上,避免每次分配中的虚拟函数调用似乎是明智的性能明智之举。而且,您仍然可以在运行时在工厂中在两者之间做出决定。此外,为什么不将分配器传递给类构造函数(然后将其作为[optional?]参数进一步传递给容器)?@Max Langhof:我知道在nearEnemyCache
中总是使用堆分配器(而不是堆栈)。分配器的实例是在运行时确定的,不过……为了简单起见,我使用了虚拟函数。我以后可能会改为模板。谢谢……将分配器传递给Car()
constructor=将脏代码移动到Car
类。我的代码的总脏代码将保持不变。谢谢。我喜欢你的singleton::get()
。它与中描述的类似。嗯,singleton/global似乎是管理分配器的最佳方式。
class CarFactory{
GameEngine* gameEngine;
Car* createCar(){
Car* car=new Car();
car->nearEnemyCache.setAllocator( gameEngine->heap );
return 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
}
template<class T, class DefaultAlloc = ChosenAtRuntimeAlloc>
class MyArray
{
public:
MyArray() : _allocator(singleton<DefaultAlloc>::get())
{
}
void setAllocator(Allocator* alloc)
{
_allocator = alloc;
}
private:
Allocator* _allocator;
};