cocos2dx对象内存管理机制分析

cocos2dx是通过引用计数的方式管理内存的。这里涉及到4个类:CCObject,CCAutoreleasePool,CCPoolManager和CCDirector;下面介绍这4个类的情况;

CCObject是cocos2dx对象的基类(这里指继承于CCObject),里面有一个m_uReference引用计数,它提供了3个主要的方法,如下:

void CCObject::release(void)
{
    CCAssert(m_uReference > 0, "reference count should greater than 0");
    --m_uReference;//计数会减1

    if (m_uReference == 0)
    {
        delete this;
    }
}

void CCObject::retain(void)
{
    CCAssert(m_uReference > 0, "reference count should greater than 0");

    ++m_uReference;
}

CCObjectCCObject::autorelease(void)
{
    CCPoolManager::sharedPoolManager()->addObject(this);
    return this;
}
    CCAutoreleasePool是自动对象池,新创建的对象会放到这里面管理,它提供了2个主要方法,如下:
ps: 代码中的m_pManagedObjectArray是CCArray类型的对象,用来存储CCObject对象。
void CCAutoreleasePool::addObject(CCObjectpObject)
{
    m_pManagedObjectArray->addObject(pObject);  //CCArray::addObject()方法会使对象计数+1,具体可进去看源码

    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.计数-1
}
void CCAutoreleasePool::clear()
{
    if(m_pManagedObjectArray->count() > 0)
    {
        //CCAutoreleasePool* pReleasePool;
#ifdef _DEBUG
        int nIndex = m_pManagedObjectArray->count() - 1;
#endif

        CCObject* pObj = NULL;
        CCARRAY_FOREACH_REVERSE(m_pManagedObjectArray, pObj)
        {
            if(!pObj)
                break;

            --(pObj->m_uAutoReleaseCount);
            //(*it)->release();
            //delete (*it);
#ifdef _DEBUG
            nIndex--;
#endif
        }

        m_pManagedObjectArray->removeAllObjects();//removeAllObjects()方法里面会遍历里面的元素,并且调用release()的,这就意味着对象的引用计数-1;
    }
}

	CCPoolManager是自动释放池的管理类,是一个singleton,主要内容如下:
    CCArray*    m_pReleasePoolStack;     //用来装CCAutoreleasePool*对象,可能不止一个对象池哦
    CCAutoreleasePool*                    m_pCurReleasePool;//当前使用的对象池

void CCPoolManager::addObject(CCObjectpObject)
{
    getCurReleasePool()->addObject(pObject); //getCurReleasePool()是取到当前使用的对象池;
}
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;*/
}

在看看CCDirector,相关代码如下:

void CCDisplayLinkDirector::mainLoop(void)
{
    if (m_bPurgeDirecotorInNextLoop)
    {
        m_bPurgeDirecotorInNextLoop = false;
        purgeDirector();
    }
    else if (! m_bInvalid)
     {
         drawScene();
     
         // release the objects
         CCPoolManager::sharedPoolManager()->pop(); 
     }
}
可以看出在  drawScene();之后会去调用 CCPoolManager::pop();就是回收对象是在帧的结尾的


下面是一个例子,假如MyClass继承CCObject:

MyClass* MyClass::create()

{

MyClass* pRet= new MyClass();

pRet->autorelease();

return pRet;

}

当某处需要创建一个MyClass类型的对象,如下:

MyClass* pMyClass = MyClass::create();

pMyClass->retain();

........

那么整个过程是什么样子的呢,往下看

MyClass::create();被调用后,先new MyClass();,此时引用计数为1(看下面代码);

CCObject::CCObject(void)
: m_nLuaID(0)
, m_uReference(1) // when the object is created, the reference count of it is 1
, m_uAutoReleaseCount(0)
{......},
然后pRet->autorelease();autorelease()就往对象池中加入一个对象:
CCPoolManager::sharedPoolManager()->addObject(this); //实际上这里的引用计数有一个+1再-1的过程,最终计数不变
此时该对象引用计数还是为1;接着pMyClass->retain();后,计数+1变为2,在这帧结束前在CCDirector中调用了
CCPoolManager::sharedPoolManager()->pop();  //这个方法会调用到CCAutoreleasePool::clear(),而clear方法中会遍历对象池中的元素并且都调用CCObject::release()方法,此时该对象的计数-1变为1了,这就是pMyClass->retain()的引用结果(当然如果还在其他地方也retain()的话,计数就不止1了,反正retain()过n次,计数就为n.)当pMyClass不用了,会调用release()方法,此时计数在-1变为0,被delete掉,ok,这个对象生命结束。
	但是可能会问,为什么需要autorelease()呢,那放过来看看,如果不用这种机制,当一个对象new后立马被delete了,那么就没法使用这个对象了。使用autorelease()从对象的new开始到帧结束前的release()之间,提供了一个让第三方引用的时机。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值