【木頭Cocos2d-x 037】retain和release倒底怎麼玩?

來源:互聯網
上載者:User

retain和release倒底怎麼玩?

 

呼呼,好久沒有發布教程了(小若:難得清靜了,你為毛又出來嚇人= =),其實最近木頭我在準備出版書籍的事情。但是貌似不太順利,果然我還是積累不夠,寫書的過程壓力好大,感覺寫不出有趣的文字出來(小若:嗷、、、)。果然還是在部落格寫自由一些?嘿嘿~

最近以及最不是很近(小若:書裡一定不能出現這些錯誤的語句,所以你才寫不出來吧= =),不少朋友對retain的認識似乎有點模糊,今天我就和大家分享一下關於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源碼層級的解說,請到紅孩兒的部落格吧,強烈推薦~

 

好了,不嘮叨了~困喇,睡大覺去~~

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.