Gri*_*ess 2 c memory-management particles particle-system
我正在构建一个简单的粒子系统,并希望使用结构的单个数组缓冲区来管理我的粒子.也就是说,我找不到允许我从任意缓冲区中取出malloc()和free()的C函数.这是一些伪代码来表明我的意图:
Particle* particles = (Particle*) malloc( sizeof(Particle) * numParticles );
Particle* firstParticle = <buffer_alloc>( particles );
initialize_particle( firstParticle );
// ... Some more stuff
if (firstParticle->life < 0)
<buffer_free>( firstParticle );
// @ program's end
free(particles);
Run Code Online (Sandbox Code Playgroud)
其中<buffer_alloc>和<buffer_free>是从任意指针分配和释放内存块的函数(可能具有诸如缓冲区长度等的附加元数据).这些功能是否存在和/或有更好的方法吗?谢谢!
是的,你必须自己写.这很简单,它真的很傻,但与单独使用malloc()和free()相比,它的性能会尖叫....
static const int maxParticles = 1000;
static Particle particleBuf[maxParticles]; // global static array
static Particle* headParticle;
void initParticleAllocator()
{
Particle* p = particleBuf;
Particle* pEnd = &particleBuf[maxParticles-1];
// create a linked list of unallocated Particles
while (p!=pEnd)
{
*((Particle**)p) = p+1;
++p;
}
*((Particle**)p) = NULL; // terminate the end of the list
headParticle = particleBuf; // point 'head' at the 1st unalloc'ed one
}
Particle* ParticleAlloc()
{
// grab the next unalloc'ed Particle from the list
Particle* ret = headParticle;
if (ret)
headParticle = *(Particle**)ret;
return ret; // will return NULL if no more available
}
void ParticleFree(Particle* p)
{
// return p to the list of unalloc'ed Particles
*((Particle**)p) = headParticle;
headParticle = p;
}
Run Code Online (Sandbox Code Playgroud)
你可以修改上面的方法,根本不用任何全局静态数组,并在用户调用ParticleAlloc()时首先使用malloc(),但是当返回Particles时,不要调用free()而是添加返回的那些未分配粒子的链表.那么ParticleAlloc()的下一个调用者将从免费粒子列表中获取一个,而不是使用malloc().只要空闲列表中没有更多内容,您的ParticleAlloc()函数就可以回退到malloc().或者使用两种策略的混合,这两种策略实际上是最好的:如果您知道您的用户几乎肯定会使用至少1000个粒子,但偶尔可能需要更多,您可以从1000的静态数组开始如果你用完了,就回到调用malloc().如果你这样做,malloc()'ed的那些不需要特殊处理; 当它们返回到ParticleFree()时,只需将它们添加到unalloc'ed粒子列表中.当你的程序退出时,你不需要在它们上面调用free(); 操作系统将释放进程的整个内存空间,因此任何泄漏的内存都会在此时清除.
我应该提一下,因为你的问题被标记为"C"而不是"C++",我以C解决方案的形式回答了它.在C++中,实现同样的事情的最好方法是在Particle类中添加"operator new"和"operator delete"方法.它们将包含与我上面显示的基本相同的代码,但是它们覆盖(不重载)全局"new"运算符,并且仅对于Particle类,定义一个替换全局"new"的专用分配器.很酷的是,Particle对象的用户甚至不必知道有一个特殊的分配器; 他们只是像往常一样使用"新"和"删除",并且仍然幸福地发现他们的粒子对象来自一个特殊的预分配池.