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
- javaScript 記憶體管理機制JavaScript記憶體
- Java記憶體管理機制Java記憶體
- Qt 記憶體管理機制QT記憶體
- jvm記憶體管理機制JVM記憶體
- Qt 記憶體管理機制薦QT記憶體
- linux記憶體管理機制Linux記憶體
- 各個執行緒 Autorelease 物件的記憶體管理執行緒物件記憶體
- 淺析java記憶體管理機制Java記憶體
- 記憶體管理機制的發展記憶體
- ARC記憶體管理機制詳解記憶體
- 什麼是記憶體管理?其最主要作用?OC記憶體管理機制?記憶體
- JVM自動記憶體管理機制 二JVM記憶體
- 淺談Linux記憶體管理機制Linux記憶體
- AIX虛擬記憶體管理機制(轉)AI記憶體
- IBM的AIX記憶體管理機制IBMAI記憶體
- Java的記憶體管理機制之記憶體區域劃分Java記憶體
- Python如何管理記憶體?記憶體分配機制是什麼?Python記憶體
- IOS基礎:retain,copy,assign及autoreleaseiOSAI
- JavaScript 記憶體機制JavaScript記憶體
- 一文洞悉JVM記憶體管理機制JVM記憶體
- Python記憶體管理機制-《原始碼解析》Python記憶體原始碼
- Objective-C中的記憶體管理機制Object記憶體
- 深度學習 Caffe 記憶體管理機制理解深度學習記憶體
- javascript的垃圾回收機制和記憶體管理JavaScript記憶體
- android記憶體管理機制與優化Android記憶體優化
- 淺談Linux的記憶體管理機制Linux記憶體
- 【江楓】AIX虛擬記憶體管理機制AI記憶體
- V8記憶體管理及垃圾回收機制記憶體
- object-c(oc)記憶體管理機制詳解Object記憶體
- JVM記憶體管理和垃圾回收機制介紹JVM記憶體
- object-c 記憶體管理機制的學習Object記憶體
- dm8127 記憶體分配和管理機制記憶體
- Linux記憶體管理Swap和Buffer Cache機制Linux記憶體
- js記憶體回收機制JS記憶體
- 【AIX】AIX記憶體機制AI記憶體
- linux記憶體機制Linux記憶體