本文基于3.2版本,适用于3.0及其以上版本,2.X版本可能是使用不同的方式进行处理,本文未对比2.X版本的源代码。首先看一下cocos2d-x中对象的继承体系:
从图中可以看出Ref是cocos2d-x中一切对象的起源(这里只列出了一部分的类),继承自Node节点的对象引擎会在每帧对其进行更新render,而Texture2D等非继承自Node节点的对象属于游戏内的数据对象。
cocos2d-X引擎使用C++编写,由于C++本身没有内存回收机制,故而cocos2d-x使用了引用计数(reference count)的方式进行内存管理,而Ref就是实现这个内存管理的关键。Ref中有一个记录对象引用次数的变量_referenceCount,retain操作将该变量+1,release是将该变量-1,当进行release操作时如果_referenceCount = 0,则将该对象进行销毁,下面看一段release和autorelease方法的代码
@H_404_35@ voidRef::release(){ @H_404_35@ --_referenceCount; @H_404_35@ if(_referenceCount == 0){ @H_404_35@ delete this ; @H_404_35@ } @H_404_35@ } | @H_404_35@ Ref* Ref::autorelease() @H_404_35@ { @H_404_35@ PoolManager::getInstance()->getCurrentPool()->addObject( this); @H_404_35@ return this ; @H_404_35@ } |
从上面的代码中可以看出release是以当前计数进行减1操作,而autorelease并不是真正意义的release操作,其是将当前对象添加到AutoreleasePool中,并且当该帧结束时由AutoreleasePool负责进行执行release操作,从而做到ARC(auto reference count)的效果。
为了进一步了解AutoreleasePool的原理,我们来看一段游戏mainLoop(游戏的主循环)的代码:
voidDisplayLinkDirector::mainLoop(){
// 省略一部分代码
{
drawScene();
// release the objects
PoolManager
::getInstance()->getCurrentPool()->clear();
}
}
|
@H_404_35@ void AutoreleasePool::clear() @H_404_35@ { @H_404_35@ for ( const auto &obj : _managedObjectArray) @H_404_35@ { @H_404_35@ obj->release(); @H_404_35@ } @H_404_35@ _managedObjectArray.clear(); @H_404_35@ } |
可以看出当当前帧绘制结束后会对AutoreleasePool中的对象进行清理,从上面的分析可以看出release和autorelease的区别:
relealse | autorelease |
直接对object进行引用计数减1,并且当引用为0时将对象析构。 | 将对象放入AutoreleasePool中,并且当当前帧结束时对放入的object进行release操作。 |
那么autorelease应该什么时候被调用呢,从Ref继承的类都实现了一个静态的create方法,当创建对象成功时会被自动添加到
AutoreleasePool
中,如下是node节点的create方法,一旦创建成功就会调用该对象的autorelease方法。
@H_404_35@
Node
*
Node
::create()