cocos2d-x中的引用计数原理
发布时间:2020-12-14 16:59:55 所属栏目:百科 来源:网络整理
导读:本文基于3.2版本,适用于3.0及其以上版本,2.X版本可能是使用不同的方式进行处理,本文未对比2.X版本的源代码。首先看一下cocos2d-x中对象的继承体系: 从图中可以看出Ref是cocos2d-x中一切对象的起源(这里只列出了一部分的类),继承自Node节点的对象引擎
本文基于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方法的代码
从上面的代码中可以看出release是以当前计数进行减1操作,而autorelease并不是真正意义的release操作,其是将当前对象添加到AutoreleasePool中,并且当该帧结束时由AutoreleasePool负责进行执行release操作,从而做到ARC(auto reference count)的效果。
为了进一步了解AutoreleasePool的原理,我们来看一段游戏mainLoop(游戏的主循环)的代码:
可以看出当当前帧绘制结束后会对AutoreleasePool中的对象进行清理,从上面的分析可以看出release和autorelease的区别:
那么autorelease应该什么时候被调用呢,从Ref继承的类都实现了一个静态的create方法,当创建对象成功时会被自动添加到
AutoreleasePool
中,如下是node节点的create方法,一旦创建成功就会调用该对象的autorelease方法。
Node
*
Node
::create()
{
Node
* ret =
new
Node
();
if
(ret && ret->init())
{
ret->autorelease();
}
else
{
CC_SAFE_DELETE
(ret);
}
return
ret;
}
下面是cocos2d-x官网上的一个例子,该例在游戏中运行时会crash,原因是m_pBombsDisplayed在create时被添加进AutoreleasePool,所以当该帧结束之后,m_pBombsDisplayed的release方法会被调用,由于create时引用计数值被设置为1,所以执行release时m_pBombsDisplayed被析构掉了,所以下一帧执行update时该对象已不复存在。
所以为了能操作update时不crash,可以在create之后m_pBombsDisplayed->retain(),将引用计数值加1,从而保证该对象不被AutoreleasePool给release掉。
bool
HelloWorld::init()
{
bool
bRet =
false
;
do
{
CCSprite* bomb1 = CCSprite::create( "CloseNormal.png" );
addChild(bomb1,1);
m_pBombsDisplayed = CCArray::create(bomb1, NULL);
//m_pBombsDisplayed->retain()
m_pBombsDisplayed->objectAtIndex(0)->setPosition(cpp(100,100));
bRet = true;
}
while
(0);
return
bRet;
}
void HelloWorld::update(ccTime dt)
{
m_pBombsDisplayed->objectAtIndex(0)->setPosition(cpp(100,100));
}
另外虽然bomb1在create时也被添加到了
AutoreleasePool并且该帧结束时也被调用release,但由于addChild方法会主动对bomb1进行retain操作,所以addChild之后其引用计数>=2,下一帧还会存在于场景中。
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
推荐文章
站长推荐
- 最佳实践在swift中实现failable初始化
- flex – 如何处理Actionscript中的Number精度?
- ios – 在XCode中缺少所需的架构arm64
- ruby-on-rails – mongoid – 在引用1..N关系中从
- 使用ajax实现动态局部刷新
- ruby-on-rails – 使用routes.rb重定向旧URL的Ra
- 从YOUTUBE.COM分析,Media Source API的AJAX实现
- c# – 在.net Core 2.0中设置环境变量
- linq to xml There are multiple root elements.
- 您使用哪些信息/视频来学习使用C#进行Web开发的新
热点阅读