Cocos2dx-記憶體管理機制(autorelease、release、retain)
原文出自 : http://blog.csdn.net/musicvs/article/details/8689345
1. 為什麼會有retain?
C++和Java不一樣,Java有一套很方便的垃圾回收機制,當我們不需要使用某個物件時,給它賦予null值即可。而C++new了一個物件之後,不使用的時候通常需要delete掉。
於是,Cocos2d-x就發明了一套記憶體管理機制(小若:發你妹紙。。。),其實紅孩兒的部落格很詳細地解釋了Cocos2d-x的記憶體管理機制,我沒有能力也不想重複解釋。(小若:那你還寫?= =)
Retain的意思是保持引用,也就是說,如果想保持某個物件的引用,避免它被Cocos2d-x釋放,那就要呼叫物件的retain函式。(小若:為什麼不retain就會被釋放?)
2. 真正的凶手autoRelease
既然旁白誠心誠意地問我,那我就光明正大地回答吧(小若:我今天沒力氣吐槽,好吧= =)。
一旦呼叫物件的autoRelease函式,那麼這個物件就被Cocos2d-x的記憶體管理機制給盯上了,如果這個物件沒人認領,那就等著被釋放吧。(小若:= =太久沒吐槽,一時不知道吐什麼好)。
3. 看程式碼實際點
說了這麼多,還是上程式碼吧。
建立一個Cocox2d-x的專案,就直接拿HelloWorldScene開刀,修改init函式,在最後新增一句程式碼:
- bool HelloWorld::init()
- {
- bool bRet = false;
- do
- {
- /* 很多程式碼被省略了。。。。。。 */
- testSprite = CCSprite::create("HelloWorld.png");
- bRet = true;
- } while (0);
- return bRet;
- }
(小若:testSprite是什麼東東?)
testSprite是一個成員變數,在標頭檔案里加上就可以了:
- class HelloWorld : public cocos2d::CCLayer
- {
- public:
- virtual bool init();
- static cocos2d::CCScene* scene();
- void menuCloseCallback(CCObject* pSender);
- CREATE_FUNC(HelloWorld);
- private:
- cocos2d::CCSprite* testSprite;
- };
然後,最關鍵的來了,我們修改menuCloseCallback函式:
- void HelloWorld::menuCloseCallback(CCObject* pSender)
- {
- testSprite->getPosition();
- }
現在,執行專案,點選按鈕,看看是什麼情況?
(小若:報錯了!)
如果大家知道怎麼除錯專案的話,我們在menuCloseCallback函式裡斷點,用除錯模式執行專案,看看testSprite物件:
(小若:很正常啊,有什麼特別的?)
正你妹紙啊,正!你才正!(小若:不要這麼光明正大地讚我O O!)
我們應該能看到不少非正常資料,圖中已經用紅色圈圈標出來了,這代表testSprite物件被釋放了,現在testSprite指向未知的位置。
這是很危險的,有時候它不會立即報錯,但是在某個時刻突然崩潰!
要想解決這個問題,很簡單,再次修改init函式:
- bool HelloWorld::init()
- {
- bool bRet = false;
- do
- {
- /* 很多程式碼被省略了。。。。。。 */
- testSprite = CCSprite::create("HelloWorld.png");
- testSprite->retain();
- bRet = true;
- } while (0);
- return bRet;
- }
再次執行專案,看看還會不會報錯?(小若:不會了,為什麼?)
再次用除錯模式執行專案,看看testSprite物件:
(小若:不正常!都是0!!)
零你妹紙= =(小若:為什麼今天你總是搶我的對白O O!)
這次我們看到testSprite的資料明顯正常了。
4. 原理來了
好了,嘮叨了一大堆,還沒有進入正題。
首先,要想讓物件參與記憶體管理機制,必須繼承CCObject類(CCNode、CCLayer等都繼承了CCObject類)。
然後,呼叫物件的autoRelease函式,物件就會被Cocos2d-x的記憶體管理機制盯上,在遊戲的每一幀,記憶體管理機制都會掃描一遍被盯上的物件,一旦發現物件無人認領,就會將物件殺死!(小若:嗷~殘忍!)
如果不想讓物件被殺死,那麼就要呼叫物件的retain函式,這樣物件就被認領了,一旦物件被認領,就永遠不會被記憶體管理機制殺掉,是永遠,一輩子。(小若:好朋友,一輩子= =)
但,物件一輩子都不被釋放的話,那麼就會產生記憶體洩露,你試試載入一個佔20M記憶體的物件一輩子不釋放,不折騰死才怪~(小若:你去載入一個20M的物件本身就是閒的那個什麼疼啊!)因此,當你不需要再使用這個物件時,就要呼叫物件的release函式,這是和retain對應的。一般可以在解構函式裡呼叫release函式。
5. 實際情況
講道理,大家都懂,但是,相信很多朋友在實際寫程式碼的時候,還是會感覺很混亂。
比如,什麼時候該retain?大家是不是發現,有時候不retain也不會報錯?
其實這很簡單,因為我們經常會在create一個物件之後,新增到層裡,如:
testSprite = CCSprite::create("HelloWorld.png");
this->addChild(testSprite);
addChild函式就是導致大家混亂的凶手了,addChild函式會呼叫物件的retain函式,為什麼它要呼叫物件的retain函式呢?因為你都把物件送給它當孩子了,它當然要認領這個物件了!(小若:我懂了,嗷!)
於是,當我們把物件addChild到CCLayer時(不一定是CCLayer,CCArray、CCNode都行),我們就不需要呼叫物件的retain函式了。
6. 那倒底什麼時候要retain?
說了這麼多,還是沒有說清楚,什麼時候要呼叫物件的retain。
很簡單,當你把一個物件作為成員變數時,並且沒有把物件addChild到另外一個物件時,就需要呼叫retain函式。
7. 最後的最後
一定要記住,必須要呼叫了物件的autoRelease函式之後,retain和release函式才會生效,否則,一切都是徒勞。
因此,十分建議使用create的方式建立物件,如:
- 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;
- }
這些就是retain表面上的知識了,至於retain原始碼級別的解說,請到紅孩兒的部落格吧,強烈推薦~
好了,不嘮叨了~困喇,睡大覺去~~
相關文章
- 記憶體管理Release和Retain實現原理記憶體AI
- Objective-C 記憶體管理之alloc/retain/release/dealloc實現原理Object記憶體AI
- IOS基礎:retain,copy,assign及autoreleaseiOSAI
- Java記憶體管理機制Java記憶體
- jvm記憶體管理機制JVM記憶體
- javaScript 記憶體管理機制JavaScript記憶體
- 淺析java記憶體管理機制Java記憶體
- 記憶體管理機制的發展記憶體
- 【記憶體管理】頁面分配機制記憶體
- Python如何管理記憶體?記憶體分配機制是什麼?Python記憶體
- JVM自動記憶體管理機制 二JVM記憶體
- Python記憶體管理機制-《原始碼解析》Python記憶體原始碼
- android記憶體管理機制與優化Android記憶體優化
- Java的記憶體管理機制之記憶體區域劃分Java記憶體
- javascript的垃圾回收機制和記憶體管理JavaScript記憶體
- 一文洞悉JVM記憶體管理機制JVM記憶體
- 深度學習 Caffe 記憶體管理機制理解深度學習記憶體
- Objective-C中的記憶體管理機制Object記憶體
- V8記憶體管理及垃圾回收機制記憶體
- js記憶體回收機制JS記憶體
- [譯] 通過垃圾回收機制理解 JavaScript 記憶體管理JavaScript記憶體
- 要點提煉| 理解JVM之記憶體管理機制JVM記憶體
- Android彈藥庫——記憶體管理機制與程式模型Android記憶體模型
- OpenHarmony 3.1 Release版本關鍵特性解析——Enhanced SWAP記憶體管理記憶體
- AntDB記憶體管理之記憶體上下文之記憶體上下文機制是怎麼實現的記憶體
- 記憶體管理 記憶體管理概述記憶體
- JVM 自動記憶體管理機制及 GC 演算法JVM記憶體GC演算法
- php原始碼02 -基本變數與記憶體管理機制PHP原始碼變數記憶體
- jvm:記憶體模型、記憶體分配及GC垃圾回收機制JVM記憶體模型GC
- 深入理解Java虛擬機器筆記-自動記憶體管理機制Java虛擬機筆記記憶體
- 深入理解Java虛擬機器(自動記憶體管理機制)Java虛擬機記憶體
- 關於JavaScript的記憶體機制JavaScript記憶體
- Java程式執行記憶體機制Java記憶體
- Redis 記憶體淘汰機制詳解Redis記憶體
- Java記憶體模型,垃圾回收機制,常用記憶體命令及工具Java記憶體模型
- Linux核心筆記002 - i386 的頁式記憶體管理機制Linux筆記記憶體
- 自動記憶體管理機制_執行時資料區域記憶體
- 記憶體管理篇——實體記憶體的管理記憶體
- 【記憶體管理】記憶體佈局記憶體