转载请注明来自 _鞋男blog:http://blog.csdn.net/wushao126/article/details/41050605
仍然是2.x与 3.x的对比
cocos2dx 2.x:
当我们创建一个精灵的时候,都会调用精灵对象的autorelease(),
CCSprite* CCSprite::create(const char *pszfilename){ CCSprite *pobSprite = new CCSprite(); if (pobSprite && pobSprite->initWithfile(pszfilename)) { pobSprite->autorelease(); return pobSprite; } CC_SAFE_DELETE(pobSprite); return NulL;}当创建一个精灵对象的时候,
CCSprite* sprite = CCSprite::create(s_pPathGrossini); cclog("sprite->retainCount()=%d",sprite->retainCount());//output:sprite->retainCount()=1 addChild(sprite,kTagsprite); cclog("sprite->retainCount()=%d",sprite->retainCount());//output:sprite->retainCount()=2跟踪
pobSprite->autorelease();跳转到了
CCObject* CCObject::autorelease(voID){ CCPoolManager::sharedPoolManager()->addobject(this); return this;}
敢说CCSprite不是CCObject的派生类!!!
有个CCPoolManager全局对象,把精灵对象加了进去
voID CCPoolManager::addobject(CCObject* pObject){ getCurReleasePool()->addobject(pObject);}
形参为CCObject* ,这就已经不用管对象是不是精灵了,我们只需要记得是个CCObject对象,至于多肽神马的有RTTI机制搞定了。
继续跟进:
voID CCPoolManager::addobject(CCObject* pObject){ getCurReleasePool()->addobject(pObject);}CCautoreleasePool* CCPoolManager::getCurReleasePool(){ if(!m_pCurReleasePool) { push();<pre name="code" > //创建一个自动释放池 并加入到释放池栈中}
CCAssert(m_pCurReleasePool,"current auto release pool should not be null");
return m_pCurReleasePool;
}
这里简单说明下,
class CC_DLL CCPoolManager{ CCArray* m_pReleasePoolStack; CCautoreleasePool* m_pCurReleasePool;public:... frIEnd class CCautoreleasePool;};
voID CCPoolManager::push(){ CCautoreleasePool* pPool = new CCautoreleasePool(); //ref = 1 m_pCurReleasePool = pPool; m_pReleasePoolStack->addobject(pPool); //ref = 2 pPool->release(); //ref = 1}
以上代码可以看出我们创建的对象被加入到一个CCArray中的一个CCautoreleasePool中,看这
voID CCautoreleasePool::addobject(CCObject* pObject){ m_pManagedobjectArray->addobject(pObject); CCAssert(pObject->m_uReference > 1,"reference count should be greater than 1"); ++(pObject->m_uautoReleaseCount); pObject->release(); // no ref count,in this case autorelease pool added.}其实在CCautoreleasePool里也维持一个CCArray,用来存放被加入的CCObject对象,m_uReference在CCObject构造器中被初始化为1,m_uautoReleaseCount +1了,但是autoRelease的时候未被引用,所以会被release,m_uReference被减1为0,因为到0的时候,那对象岂不是挂了,看下面代码
voID ccArrayAppendobject(ccArray *arr,CCObject* object){ CCAssert(object != NulL,"InvalID parameter!"); object->retain(); arr->arr[arr->num] = object; arr->num++;}这个全局函数式CCArray::addobject调用,在这里retain()了对象,m_uReference为2,但是我们没有引用,所以在这里release了下
voID CCObject::release(voID){ CCAssert(m_uReference > 0,"reference count should greater than 0"); --m_uReference; if (m_uReference == 0) { delete this; }}至于CCArray是什么机制,这个以后会讲到的
以上基本把retain(),release(),autorelease()讲了个遍。
接下来将引擎如果管理CCautoreleasePool的:
int CCApplication::run(){... while(1){ ... if (nNow.QuadPart - nLast.QuadPart > m_nAnimationInterval.QuadPart) { nLast.QuadPart = nNow.QuadPart; CCDirector::sharedDirector()->mainLoop();// } ... }}CCDirector游戏引擎的管理者,这里介绍mainLoop(),顾名思义,主循环,任何系统都有它的死循环,这个也不例外。进去看看:
voID CCdisplaylinkDirector::mainLoop(voID){ if (m_bPurgeDirecotorInNextLoop) { m_bPurgeDirecotorInNextLoop = false; purgeDirector(); } else if (! m_bInvalID) { drawScene(); // release the objects CCPoolManager::sharedPoolManager()->pop(); }}这个也没什么与内存有关的也就是pop(),且看pop():
voID CCPoolManager::pop(){ if (! m_pCurReleasePool) { return; } int nCount = m_pReleasePoolStack->count(); m_pCurReleasePool->clear(); if(nCount > 1) { m_pReleasePoolStack->removeObjectAtIndex(nCount-1);// if(nCount > 1)// {// m_pCurReleasePool = m_pReleasePoolStack->objectAtIndex(nCount - 2);// return;// } m_pCurReleasePool = (CCautoreleasePool*)m_pReleasePoolStack->objectAtIndex(nCount - 2); } /*m_pCurReleasePool = NulL;*/}上面说明了m_pReleasePoolStack存放的是CCautoreleasePool对象,是个CCArray*,如果把这个CCArray看成一个栈,就将栈顶d出,addobject会调用retain(),同理,removeObject会调用一次release(),但凡栈内m_uReference==1的对象将会被释放掉,因为没有被引用。
若连续两次autorelease会怎样?
cocos2dx 2.x.x内存管理我也只了解这么多,欢迎留言探讨。
原创BLOG : _鞋男 http://blog.csdn.net/wushao126/article/details/41050605
cocos2dx 3.x内存管理机制与2.x差不多,数据结构改变了,用vector<>代替了CCArray,在addobject是无需retain再release,实现方便了不少
voID displaylinkDirector::mainLoop(){ if (_purgeDirectorInNextLoop) { _purgeDirectorInNextLoop = false; purgeDirector(); } else if (! _invalID) { drawScene(); // release the objects PoolManager::getInstance()->getCurrentPool()->clear(); }}
voID autoreleasePool::clear(){#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0) _isClearing = true;#endif for (const auto &obj : _managedobjectArray) { obj->release(); } _managedobjectArray.clear();#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0) _isClearing = false;#endif}
voID Ref::release(){ CCASSERT(_referenceCount > 0,"reference count should greater than 0"); --_referenceCount; if (_referenceCount == 0) {#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0) auto poolManager = PoolManager::getInstance(); if (!poolManager->getCurrentPool()->isClearing() && poolManager->isObjectInPools(this)) { CCASSERT(false,"The reference shouldn't be 0 because it is still in autorelease pool."); }#endif#if CC_USE_MEM_LEAK_DETECTION untrackRef(this);#endif delete this; }}上面三段代码是每帧PoolManager管理内存池的代码,对照着2.x的也不难理解。
Ref* Ref::autorelease(){ PoolManager::getInstance()->getCurrentPool()->addobject(this); return this;}
voID autoreleasePool::addobject(Ref* object){ _managedobjectArray.push_back(object);}由于用的是STL,所以在这里没有个调用retain(),看起来清爽多了 ,简简单单 总结
以上是内存溢出为你收集整理的cocos2dx 3.x 自学笔记 <三> cocos2dx 2.x 3.x 内存管理机制全部内容,希望文章能够帮你解决cocos2dx 3.x 自学笔记 <三> cocos2dx 2.x 3.x 内存管理机制所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)