天天看點

cocos2d-x記憶體管理retain和release

cocos2d-x和objective-c中的retain()和release()

因為功能和接口和objective-c版本的差不多,是以在記憶體管理上也采用objective-c引用計數的機制來實作記憶體管理。仔細看了一下cocos2d-x的源代碼,确實寫的很好,代碼組織得很工整。它們所有類都是繼承自CCObject, CCObject有retain(), release()和autorelease()等方法,和objective-c上的NSObject用法一緻。每當CCObject對象初始化時它的引用計數reference-count為1, 調用retain()方法reference-count加1, 調用release()方法reference-count減1,當reference-count為0時釋放該對象記憶體。autorelease()方法的作用是對象放進CCAutoreleasePool中進行管理,每當一次繪圖結束後,CCPoolManager會對目前的記憶體池每個對象調用release()方法,一些reference-count為0的對象就會被記憶體釋放。

每當通過new, copy方法擷取一個對象時,都有義務在不用它的時候調用release()方法,如果我們是從其他方法中(例如靜态方法)就不要調用release()方法,除非之前調用了retain()方法來表示要擁有這個對象一段時間。自定義每個類裡的成員變量如果是繼承自CCObject,在賦新值之前要先對新值retain(), 然後對舊值release(),這兩個步驟不能省去或者調轉。定義方法要傳回一個對象時,如果該對象是在方法裡通過new, copy來建立的,在傳回該對象之前要調用autorelease()方法,例如很多類的靜态方法傳回它的執行個體時,都已經調用了autorelease()方法。

隻要嚴格遵守以上規範,記憶體洩漏的問題應該是可以避免的,以後寫c++程式時候,即使沒有使用cocos2d-x, 都可以考慮引入通過引

用計數來管理記憶體這一套機制,既簡單又有效。

cocos2dx記憶體管理

轉自:http://4137613.blog.51cto.com/4127613/784134

一、概述

cocos2d-x最初移植自cocos2d的objective C版本。是以,在記憶體管理上,使用了和NSObject類似的引用計數器方法,相關接口放置在CCObject類中。

二、引用計數器——手動管理記憶體

CCObject的及其子類的對象在建立時,引用計數自動設定為1。之後每次調用retain,引用計數+1。每次調用release,引用計數-1;若引用計數=0,則直接delete this。

相關接口如下:

//引用次數+1 virtual void CCObject::retain(void); //引用次數-1;若引用計數器=0,則delete this; virtual void CCObject::release(void); //helper方法,快速判斷目前對象隻有唯一引用 bool CCObject::isSingleRefrence(void); //傳回引用次數 unsigned int CCObject::retainCount(void);

原則1:誰生成(new、copy)誰負責release。

例子:

CCObject *obj=new CCObject; ... obj->release();

retain是在指針傳遞和指派時使用的,他的含義是表示擁有。這經常用在指針指派上。

原則2:誰retain,誰負責release。

例子:

obj->retain(); ... obj->release();

原則3:傳遞指派時,需要先retain形參,後release原指針,最後指派。(注意,因為這裡沒有使用自指派檢查,是以這組順序不能錯。)

例子:

void CCNode::setGrid(CCGridBase* pGrid) {             CC_SAFE_RETAIN(pGrid);             CC_SAFE_RELEASE(m_pGrid);             m_pGrid = pGrid; }

三、自動釋放池——自動管理記憶體

原則4:對于使用autorelease的對象,不必管它,每幀結束後會自動釋放。

相關接口:

CCObject* CCObject::autorelease(void); 

例子:

CCObject *obj=new CCOjbect; obj->autorelease(); ... 完全手動管理記憶體,很繁瑣,cocos2d-x提供了自動釋放池CCPoolManager。将對象置于自動釋放池中,每幀繪制結束,就自動release池中的對象。

四、CCNode節點管理

cocos2d-x使用節點組成一棵樹,渲染的時候要周遊這棵樹。CCNode是所有節點類的父類,他内部使用了一個CCArray對象管理他的所有子節點,當對象被添加為子節點時,實際上是被添加到CCArray對象中,同時會調用這個對象的retain方法。同理,從CCArray中移除時,也會調用release方法。

相關接口:

virtual void addChild(CCNode * child); virtual void addChild(CCNode * child, int zOrder); virtual void addChild(CCNode * child, int zOrder, int tag); virtual void removeChild(CCNode* child, bool cleanup); void removeChildByTag(int tag, bool cleanup); virtual void removeAllChildrenWithCleanup(bool cleanup);

在切換場景時,系統會周遊整棵樹的節點,進行release。

五、靜态工廠

cocos2d-x中存在大量的靜态工廠方法,這些方法中,全都對this指針調用了autorelease函數。如CCSprite中的這些方法:

static CCSprite* spriteWithTexture(CCTexture2D *pTexture); static CCSprite* spriteWithTexture(CCTexture2D *pTexture, const CCRect& rect); static CCSprite* spriteWithTexture(CCTexture2D *pTexture, const CCRect& rect, const CCPoint& offset); static CCSprite* spriteWithSpriteFrame(CCSpriteFrame *pSpriteFrame); static CCSprite* spriteWithSpriteFrameName(const char *pszSpriteFrameName); static CCSprite* spriteWithFile(const char *pszFileName); static CCSprite* spriteWithFile(const char *pszFileName, const CCRect& rect); static CCSprite* spriteWithBatchNode(CCSpriteBatchNode *batchNode, const CCRect& rect); 

這些方法内部實作了:記憶體配置設定、初始化、設定autorelease。用靜态工廠來生成對象,可以簡化代碼,是官方建議的方法。

cocos2dx的對象如果是create建立的,一般會調用init和autorelease,不需要自己再手動釋放

如果是自己new的,可以在new之後調用autorelease,也可以在合适的時候自己調用對象的release方法釋放

autorelease和release都是CCObject的方法

六、cache機制類

cocos2d-x中存在一些cache類,這些都是單例類的管理器。

CCAnimationCache

CCSpriteFrameCache

CCTextureCache

這些cache内部也使用了ratain和release方法,防止這些資源被釋放掉。

使用這些cache,我們可以儲存預加載的一些資源,在友善的時候調用它,去綁定給一些對象。注意,這些cache在場景切換時,不會自動删除,需要手動調用purgeXXXX方法,進行清理。

繼續閱讀