2011-12-24 72 views
1

我正在制作一个小型游戏引擎,并且需要有一个与之关联的内存池。 我的问题是,我该如何将这些内存分享给有自己班级的用户?C++ - 游戏引擎中的内存池和对象分配

例如,我有一个用户在他的游戏中获得了这个类;

class Monkey : public GameObject { 
public: 
    Monkey(); 
    ~Monkey(); 

    void Eat(); 
    void Sleep(); 

    unsigned long size(); 

private: 
    int health; 
}; 

我得到了一个基类,它目前只是返回派生类的大小。我想这将需要知道这将占用多少空间在游泳池。

public GameObject { 
public: 
    virtual unsigned long size()=0; 
}; 

他想在我的内存池中分配这个类的新实例。 我不知道在编译时的类定义,所以我只是不知道实际的方法调用将如何。他不能向我传递一个从GameObject继承的对象,因为这意味着他已经分配了它,这违背了预先分配的内存池的目的。那么,如何保留内存实际上适用于任何任意类的实例呢?

很抱歉,如果有固定的大小不明确的

+1

首先,这属于[gamedev.se](http://gamedev.stackexchange.com/)。其次,为什么你需要在内存池中分配用户派生的对象? – 2011-12-25 00:04:40

+0

内存池分配固定大小的块,我不明白你为什么需要这个大小,因为它是不变的。 – Pubby 2011-12-25 00:06:37

+0

虽然不一定与游戏相关,但在内存池上更一般,游戏引擎就是一个例子。像我想象的那样,在内存池中分配用户对象的原因是避免必须在堆上分配它,这需要时间来分配/释放,不是?在实时应用程序中,具有快速分配的内存池听起来不错 – KaiserJohaan 2011-12-25 00:08:38

回答

3

Memory pools只允许分配。因此,如果您尝试使用一个分配可变大小的对象,那么分配的固定大小就是您可以分配的最大大小。

如果你想超载分配行为,你需要在你的基类上重载operator new/delete。如果用户尝试分配超出内存池最大大小的类型,它应该为throw std::bad_alloc。此外,您应该将operator new[]/delete[]重载为throw std::bad_alloc,因为分配这些数组可能不是一个好主意。

超载operator new/delete将被赋予它正在分配的类型的正确大小。所有派生类将继承重载的操作符......除非用户覆盖它。如果他们这样做......把他们打倒。

超载本身很简单:

public GameObject { 
public: 
    void *operator new(size_t size); 
    void operator delete(void *memory); 
}; 

您将通过调用您的池获取的内存块,或解除分配的内存块实现这些。

0

让您的池充当malloc。构建对象使用放置新的池外:

object1* x = new (alloc()) object1(); 
object2* y = new (alloc()) object2(); 

x->~object1(); free(x); 
y->~object2(); free(y); 

// this can (and should) be wrapped in functions, such as operator new/delete 

有更好的方法可以做到这一点,但是这将与池不知道你的类的申报工作。

+0

请注意,如果'object1'或'object2'对于池太大,这将导致所有恶劣的庄园。 – 2011-12-25 00:21:19

+0

@NicolBolas添加了parens。是的,客户应该确保物体足够小。 – Pubby 2011-12-25 00:25:01

1

您的内存池将提供用于分配内存的API,您将执行operator new静态成员函数,该函数将您的池用于基类,或者让客户端使用放置new来构建他们想要分配给内存的内存池。

在第一种情况下,分配和破坏将是完全正常的,因为标准new运营商和delete运营商将最终调用您的自定义operator newoperator delete。所以它应该对您的客户完全透明。但是,只有继承heirarchy中的对象才能分配到您的池中。

第二种方法稍有不同,因为它需要客户的参与。他们必须手动分配/释放内存和构造/销毁对象(这很困难且不安全),或者他们会使用智能指针与自定义删除器来销毁对象并释放内存。使用这种方法,客户端可以将任何他们想要的内容放入池中,包括不从任何东西继承的类型,如大量的双打。

0

KaiserJohann,你似乎指定的是允许动态分配可变大小元素的系统。这几乎是一个动态分配器的请求。

这是我的文章Dynamic/Pool Hybrid Allocation,它应该帮助你处理你的情况。