coco2dx内存管理(源码版本:cocos2d-x-2.2.3)

来源:互联网 发布:怎么挑选电子琴知乎 编辑:程序博客网 时间:2024/06/05 02:07

深入的了解cocos2dx内存管理可以知道cocos2dx在这方面所做的动作,这样可以减少在开发的时候遇到的意料之外的错误。

cocos2dx的内存管理类名叫:CCobject。这个类用到的地方非常多,甚至可以说这个类是所有cocos2dx类的基类。虽然也有一些类没有从这个类继承内存管理功能,不过非常少。

CCObject类继承自CCCopying类,从CCCopying的名字来看主要是提供对象拷贝的重载,类的定义也证实了这一点。

class CC_DLL CCCopying{public:    virtual CCObject* copyWithZone(CCZone* pZone);};

cocos2dx的内存管理分为2种,一种是基于引用计数的判断删除对象,一种是每绘制一帧后来进行自动释放对象。另外,cocos2dx的内存管理并不像boost的智能指针那样,在对象离开作用域之后自动删除内存(引用计数),在cocos2dx里边如果要删除对象还需要显示的调用CCObject::release()函数。

第一种内存管理主要是通过CCObject对象的两个函数来进行:retain()和release()。对象调用retain使得引用计数增加1(在创建的时候引用计数初始化为1),release使得对象引用计数减一,但不会立即删除内存,只有对象持有的引用计数等于0的时候才会删除对象。

CCObject::CCObject(void): m_nLuaID(0), m_uReference(1) // when the object is created, the reference count of it is 1, m_uAutoReleaseCount(0){    static unsigned int uObjectCount = 0;    m_uID = ++uObjectCount;}
void CCObject::release(void){    CCAssert(m_uReference > 0, "reference count should greater than 0");    --m_uReference;    if (m_uReference == 0)    {        delete this;    }}void CCObject::retain(void){    CCAssert(m_uReference > 0, "reference count should greater than 0");    ++m_uReference;}

第二种内存管理初看略显复杂,但是理清楚之后却觉得简单了。还记得在mainloop()函数中,有这么一行代码:

CCPoolManager::sharedPoolManager()->pop();    

这一行的作用是release掉当前栈顶内存池里边所有的对象,而且需要注意的是在函数里边只是调用release()函数而已并没有直接delete掉对象。贴一下pop函数的代码以及注释。这里有一个意外的情况,那就是如果在对象池释放对象之前对象被删除了怎么办?会不会造成野指针呢?答案是不会,在CCObject函数里边会检查m_uAutoReleaseCount变量,如果大于0那么就从对象池里边删除掉该对象。

CCObject::~CCObject(void){    // if the object is managed, we should remove it    // from pool manager    if (m_uAutoReleaseCount > 0)    {        CCPoolManager::sharedPoolManager()->removeObject(this);    }    // if the object is referenced by Lua engine, remove it    if (m_nLuaID)    {
        CCScriptEngineManager::sharedManager()->getScriptEngine()->removeScriptObjectByCCObject(this);    }    else    {        CCScriptEngineProtocol* pEngine = CCScriptEngineManager::sharedManager()->getScriptEngine();        if (pEngine != NULL && pEngine->getScriptType() == kScriptTypeJavascript)        {            pEngine->removeScriptObjectByCCObject(this);        }    }}
贴一下CCPoolManager::sharedPoolManager()->pop();  的代码

void CCPoolManager::pop(){//当前栈顶内存池是否有分配。    if (! m_pCurReleasePool)    {        return;    }//取得栈里边所有内存池数量。     int nCount = m_pReleasePoolStack->count(); //释放掉当前栈顶内存池内存,调用release(),并没有直接delete this。    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_pCurReleasePool->clear()源码及注释

void CCAutoreleasePool::clear(){//内存池对象数组。    if(m_pManagedObjectArray->count() > 0)    {        //CCAutoreleasePool* pReleasePool;#ifdef _DEBUG        int nIndex = m_pManagedObjectArray->count() - 1;#endif        CCObject* pObj = NULL;//循环释放掉autoreleasecount标记。        CCARRAY_FOREACH_REVERSE(m_pManagedObjectArray, pObj)        {            if(!pObj)                break;            --(pObj->m_uAutoReleaseCount);            //(*it)->release();            //delete (*it);#ifdef _DEBUG            nIndex--;#endif        }//释放掉所有保存的对象。调用release()        m_pManagedObjectArray->removeAllObjects();    }}
看一下m_pManagedObjectArray->removeAllObjects()里边发生了什么。
void CCArray::removeAllObjects(){    ccArrayRemoveAllObjects(data);}
/** Removes all objects from arr */void ccArrayRemoveAllObjects(ccArray *arr){while( arr->num > 0 )    {(arr->arr[--arr->num])->release();    }}

如果需要将对象放到内存池进行自动释放管理只需要调用CCObject::autorelease()就可以了。

至此,cocos2dx的内存管理分析到这了,希望大家能有所收获^_^!

0 0