cocos2dx 3.x 自学笔记 <三> cocos2dx 2.x 3.x 内存管理机制

cocos2dx 3.x 自学笔记 <三> cocos2dx 2.x 3.x 内存管理机制,第1张

概述转载请注明来自 _鞋男blog:http://blog.csdn.net/wushao126/article/details/41050605 仍然是2.x 与 3.x 的对比 cocos2dx 2.x: 当我们创建一个精灵的时候,都会调用精灵对象的autorelease(), CCSprite* CCSprite::create(const char *pszFileName){ CC

转载请注明来自 _鞋男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 内存管理机制所遇到的程序开发问题。

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

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

原文地址: https://outofmemory.cn/web/1010469.html

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

发表评论

登录后才能评论

评论列表(0条)

保存