cocos2d-x中的引用计数原理

cocos2d-x中的引用计数原理,第1张

概述本文基于3.2版本,适用于3.0及其以上版本,2.X版本可能是使用不同的方式进行处理,本文未对比2.X版本的源代码。首先看一下cocos2d-x中对象的继承体系:                                                 从图中可以看出Ref是cocos2d-x中一切对象的起源(这里只列出了一部分的类),继承自Node节点的对象引擎会在每帧对其进行更新rend 本文基于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方法的代码
voIDRef::release(){ --_referenceCount; if(_referenceCount == 0){ delete this ; } } Ref* Ref::autorelease() { PoolManager::getInstance()->getCurrentPool()->addobject( this); return this ; }

从上面的代码中可以看出release是以当前计数进行减1 *** 作,而autorelease并不是真正意义的release *** 作,其是将当前对象添加到autoreleasePool中,并且当该帧结束时由autoreleasePool负责进行执行release *** 作,从而做到ARC(auto reference count)的效果。
为了进一步了解autoreleasePool的原理,我们来看一段游戏mainLoop(游戏的主循环)的代码:
voIDdisplaylinkDirector::mainLoop(){ // 省略一部分代码 { drawScene(); // release the objects PoolManager ::getInstance()->getCurrentPool()->clear(); } } voID autoreleasePool::clear() { for ( const auto &obj : _managedobjectArray) { obj->release(); } _managedobjectArray.clear(); }



可以看出当当前帧绘制结束后会对autoreleasePool中的对象进行清理,从上面的分析可以看出release和autorelease的区别:
relealse autorelease
直接对object进行引用计数减1,并且当引用为0时将对象析构。 将对象放入autoreleasePool中,并且当当前帧结束时对放入的object进行release *** 作。

那么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,下一帧还会存在于场景中。 总结

以上是内存溢出为你收集整理的cocos2d-x中的引用计数原理全部内容,希望文章能够帮你解决cocos2d-x中的引用计数原理所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1079071.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存