将分配器分配给字段 - 我应该将默认分配器创建为全局变量吗?

时间:2018-06-07 09:32:06

标签: c++ singleton c++14 allocator

我的游戏引擎有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;
    }
};

这是图表: -

enter image description here

问题

如果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
}

类似问题: -

1 个答案:

答案 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!"类只会抛出异常。

如果始终知道您的容器将使用哪些分配器(即您永远不必默认第二个模板参数),那么您甚至可以从分配器中消除所有虚拟功能,而是允许编译器内联所有这些。这基本上就像标准库容器那样。

相关问题