cocos2d-x精灵内存管理

转自:http://blog.csdn.net/qq276592716/article/details/12970623

 

  1.  1bool HelloWorld::init()  
  2.  2{  
  3.  3    bool bRet = false;  
  4.  4    do  
  5.  5    {  
  6.  6        //  
  7.  7        // super init first  
  8.  8        //  
  9.  9  
  10. 10        CC_BREAK_IF(! CCLayer::init());  
  11. 11  
  12. 12        //  
  13. 13        // add your codes below...  
  14. 14        //  
  15. 15  
  16. 16        CCSprite* bomb1 = CCSprite::create("CloseNormal.png");  
  17. 17        CCSprite* bomb2 = CCSprite::create("CloseNormal.png");  
  18. 18        CCSprite* bomb3 = CCSprite::create("CloseNormal.png");  
  19. 19        CCSprite* bomb4 = CCSprite::create("CloseNormal.png");  
  20. 20        CCSprite* bomb5 = CCSprite::create("CloseNormal.png");  
  21. 21        CCSprite* bomb6 = CCSprite::create("CloseNormal.png");  
  22. 22  
  23. 23        addChild(bomb1,1);  
  24. 24        addChild(bomb2,1);  
  25. 25        addChild(bomb3,1);  
  26. 26        addChild(bomb4,1);  
  27. 27        addChild(bomb5,1);  
  28. 28        addChild(bomb6,1);  
  29. 29  
  30. 30  m_pBombsDisplayed= CCArray::create(bomb1,bomb2,bomb3,bomb4,bomb5,bomb6,NULL);  
  31. 31        //m_pBombsDisplayed is defined in the header as a protected var.  
  32. 32        // <--- We should add m_pBombsDisplayed->retain() here to avoid crashing in           
  33.              HelloWorld::refreshData()  
  34. 33  
  35. 34        this->scheduleUpdate();  
  36. 35  
  37. 36        bRet = true;  
  38. 37    } while (0);  
  39. 38  
  40. 39    return bRet;  
  41. 40}  
  42. 41  
  43. 42void HelloWorld::update(ccTime dt)  
  44. 43{  
  45. 44    refreshData();  
  46. 45}  
  47. 46  
  48. 47void HelloWorld::refreshData()  
  49. 48{  
  50. 49    m_pBombsDisplayed->objectAtIndex(0)->setPosition(cpp(100,100));  
  51. 50}  
 1bool HelloWorld::init()
 2{
 3    bool bRet = false;
 4    do
 5    {
 6        //
 7        // super init first
 8        //
 9
10        CC_BREAK_IF(! CCLayer::init());
11
12        //
13        // add your codes below...
14        //
15
16        CCSprite* bomb1 = CCSprite::create("CloseNormal.png");
17        CCSprite* bomb2 = CCSprite::create("CloseNormal.png");
18        CCSprite* bomb3 = CCSprite::create("CloseNormal.png");
19        CCSprite* bomb4 = CCSprite::create("CloseNormal.png");
20        CCSprite* bomb5 = CCSprite::create("CloseNormal.png");
21        CCSprite* bomb6 = CCSprite::create("CloseNormal.png");
22
23        addChild(bomb1,1);
24        addChild(bomb2,1);
25        addChild(bomb3,1);
26        addChild(bomb4,1);
27        addChild(bomb5,1);
28        addChild(bomb6,1);
29
30  m_pBombsDisplayed= CCArray::create(bomb1,bomb2,bomb3,bomb4,bomb5,bomb6,NULL);
31        //m_pBombsDisplayed is defined in the header as a protected var.
32        // <--- We should add m_pBombsDisplayed->retain() here to avoid crashing in 		
             HelloWorld::refreshData()
33
34        this->scheduleUpdate();
35
36        bRet = true;
37    } while (0);
38
39    return bRet;
40}
41
42void HelloWorld::update(ccTime dt)
43{
44    refreshData();
45}
46
47void HelloWorld::refreshData()
48{
49    m_pBombsDisplayed->objectAtIndex(0)->setPosition(cpp(100,100));
50}

1.上面的bomb精灵在函数结束后是否会释放?

跟踪addChild函数可以看到

  1. void CCNode::addChild(CCNode *child, int zOrder, int tag)  
  2. {      
  3.     CCAssert( child != NULL, "Argument must be non-nil");  
  4.     CCAssert( child->m_pParent == NULL, "child already added. It can't be added again");  
  5.   
  6.     if( ! m_pChildren )//构造children数组  
  7.     {  
  8.         this->childrenAlloc();  
  9.     }  
  10.   
  11.     this->insertChild(child, zOrder);  //重点  
  12.   
  13.     child->m_nTag = tag;  
  14.   
  15.     child->setParent(this);  
  16.     child->setOrderOfArrival(s_globalOrderOfArrival++);  
  17.   
  18.     if( m_bRunning )  
  19.     {  
  20.         child->onEnter();  
  21.         child->onEnterTransitionDidFinish();  
  22.     }  
  23. }  
void CCNode::addChild(CCNode *child, int zOrder, int tag)
{    
    CCAssert( child != NULL, "Argument must be non-nil");
    CCAssert( child->m_pParent == NULL, "child already added. It can't be added again");

    if( ! m_pChildren )//构造children数组
    {
        this->childrenAlloc();
    }

    this->insertChild(child, zOrder);  //重点

    child->m_nTag = tag;

    child->setParent(this);
    child->setOrderOfArrival(s_globalOrderOfArrival++);

    if( m_bRunning )
    {
        child->onEnter();
        child->onEnterTransitionDidFinish();
    }
}

进入insertChild

  1. void CCNode::insertChild(CCNode* child, int z)  
  2. {  
  3.     m_bReorderChildDirty = true;  
  4.     ccArrayAppendObjectWithResize(m_pChildren->data, child); //重点,初始化children数组  
  5.     child->_setZOrder(z);  
  6. }  
void CCNode::insertChild(CCNode* child, int z)
{
    m_bReorderChildDirty = true;
    ccArrayAppendObjectWithResize(m_pChildren->data, child); //重点,初始化children数组
    child->_setZOrder(z);
}

进入ccArrayAppendObjectWithResize

  1. void ccArrayAppendObjectWithResize(ccArray *arr, CCObject* object)  
  2. {  
  3.     ccArrayEnsureExtraCapacity(arr, 1);  
  4.     ccArrayAppendObject(arr, object); //重点  
  5. }  
void ccArrayAppendObjectWithResize(ccArray *arr, CCObject* object)
{
	ccArrayEnsureExtraCapacity(arr, 1);
	ccArrayAppendObject(arr, object); //重点
}

进入ccArrayAppendObject

  1. void ccArrayAppendObject(ccArray *arr, CCObject* object)  
  2. {  
  3.     CCAssert(object != NULL, "Invalid parameter!");  
  4.     object->retain();   //真相大白  
  5.     arr->arr[arr->num] = object;  
  6.     arr->num++;  
  7. }  
void ccArrayAppendObject(ccArray *arr, CCObject* object)
{
    CCAssert(object != NULL, "Invalid parameter!");
    object->retain();   //真相大白
	arr->arr[arr->num] = object;
	arr->num++;
}

ccArrayAppendObject里面进行了引用计数的+1,使得在函数结束后对象不会被自动回收。


2.上面的bomb精灵在什么时候释放?

见ccnode的析构函数

  1. CCNode::~CCNode(void)  
  2. {  
  3.     CCLOGINFO( "cocos2d: deallocing" );  
  4.       
  5.     unregisterScriptHandler();  
  6.     if (m_nUpdateScriptHandler)  
  7.     {  
  8.         CCScriptEngineManager::sharedManager()->getScriptEngine()->removeScriptHandler(m_nUpdateScriptHandler);  
  9.     }  
  10.   
  11.     CC_SAFE_RELEASE(m_pActionManager);  
  12.     CC_SAFE_RELEASE(m_pScheduler);  
  13.     // attributes  
  14.     CC_SAFE_RELEASE(m_pCamera);  
  15.   
  16.     CC_SAFE_RELEASE(m_pGrid);  
  17.     CC_SAFE_RELEASE(m_pShaderProgram);  
  18.     CC_SAFE_RELEASE(m_pUserObject);  
  19.   
  20.     if(m_pChildren && m_pChildren->count() > 0)  
  21.     {  
  22.         CCObject* child;  
  23.         CCARRAY_FOREACH(m_pChildren, child)  
  24.         {  
  25.             CCNode* pChild = (CCNode*) child;  
  26.             if (pChild)  
  27.             {  
  28.                 pChild->m_pParent = NULL;  
  29.             }  
  30.         }  
  31.     }  
  32.   
  33.     // children  
  34.     CC_SAFE_RELEASE(m_pChildren);  //这边,降低m_pChildren的引用计数,使其释放  
  35.       
  36.           // m_pComsContainer  
  37.     m_pComponentContainer->removeAll();  
  38.     CC_SAFE_DELETE(m_pComponentContainer);  
  39. }  
CCNode::~CCNode(void)
{
    CCLOGINFO( "cocos2d: deallocing" );
    
    unregisterScriptHandler();
    if (m_nUpdateScriptHandler)
    {
        CCScriptEngineManager::sharedManager()->getScriptEngine()->removeScriptHandler(m_nUpdateScriptHandler);
    }

    CC_SAFE_RELEASE(m_pActionManager);
    CC_SAFE_RELEASE(m_pScheduler);
    // attributes
    CC_SAFE_RELEASE(m_pCamera);

    CC_SAFE_RELEASE(m_pGrid);
    CC_SAFE_RELEASE(m_pShaderProgram);
    CC_SAFE_RELEASE(m_pUserObject);

    if(m_pChildren && m_pChildren->count() > 0)
    {
        CCObject* child;
        CCARRAY_FOREACH(m_pChildren, child)
        {
            CCNode* pChild = (CCNode*) child;
            if (pChild)
            {
                pChild->m_pParent = NULL;
            }
        }
    }

    // children
    CC_SAFE_RELEASE(m_pChildren);  //这边,降低m_pChildren的引用计数,使其释放
    
          // m_pComsContainer
    m_pComponentContainer->removeAll();
    CC_SAFE_DELETE(m_pComponentContainer);
}

CCARRAY的释放会调用到

  1. /** Frees array after removing all remaining objects. Silently ignores NULL arr. */  
  2. void ccArrayFree(ccArray*& arr)  
  3. {  
  4.     if( arr == NULL )   
  5.     {  
  6.         return;  
  7.     }  
  8.     ccArrayRemoveAllObjects(arr);  
  9.       
  10.     free(arr->arr);  
  11.     free(arr);  
  12.   
  13.     arr = NULL;  
  14. }  
/** Frees array after removing all remaining objects. Silently ignores NULL arr. */
void ccArrayFree(ccArray*& arr)
{
    if( arr == NULL ) 
    {
        return;
    }
	ccArrayRemoveAllObjects(arr);
	
	free(arr->arr);
	free(arr);

    arr = NULL;
}

进入ccArrayRemoveAllObjects

  1. /** Removes all objects from arr */  
  2. void ccArrayRemoveAllObjects(ccArray *arr)  
  3. {  
  4.     while( arr->num > 0 )  
  5.     {  
  6.         (arr->arr[--arr->num])->release();  //每个元素的引用计数-1,使其释放  
  7.     }  
  8. }  
/** Removes all objects from arr */
void ccArrayRemoveAllObjects(ccArray *arr)
{
	while( arr->num > 0 )
    {
		(arr->arr[--arr->num])->release();  //每个元素的引用计数-1,使其释放
    }
}

3.上面的m_pBombsDisplayed会在什么时候释放?

  见CCARRAYcreate函数,create后引用计数为1,在函数结束后-1为0被释放

  1. CCArray* CCArray::create()  
  2. {  
  3.     CCArray* pArray = new CCArray();  
  4.   
  5.     if (pArray && pArray->init())  
  6.     {  
  7.         pArray->autorelease(); //放入了autorelease里面,引用计数在函数结束自动-1,被回收。  
  8.     }  
  9.     else  
  10.     {  
  11.         CC_SAFE_DELETE(pArray);  
  12.     }  
  13.       
  14.     return pArray;  
  15. }  
CCArray* CCArray::create()
{
    CCArray* pArray = new CCArray();

    if (pArray && pArray->init())
    {
        pArray->autorelease(); //放入了autorelease里面,引用计数在函数结束自动-1,被回收。
    }
    else
    {
        CC_SAFE_DELETE(pArray);
    }
    
    return pArray;
}

4.解决m_pBombsDisplayed的问题,主动retain,在helloworld析构的时候release

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值