天天看點

【轉】對cocos2d 之autorelease\ratain\release的了解

原文連結:http://blog.sina.com.cn/s/blog_4057ab6201018y4y.html

Objective C記憶體管理進階(二):了解autorelease:

http://www.cnblogs.com/MobileDevelop/archive/2010/07/19/1779138.html

看了上面部落格中對autorelease的見解,對autorelease有了更深入的了解。但是還不是很了解,于是又看了代碼。一開始對autorelease的“自動釋放”的印象總是揮之不去。總是往java那樣的完全自動釋放那方面靠,于是第一感覺就錯了。

以下僅針對 cocos2dx分析。

前言:

三種情況,引出問題

    new出來的對象需要釋放,而釋放時,如果有其他人引用了這個對象,再次使用這個對象時,則會導緻無效指針報錯。

    于是有了引用計數的施放管理機制。

    對于一個傳回對象指針的方法。你若不看文檔不看内部代碼,你無法知道傳回的這個指針需不需要你來釋放。同樣的對于将一個指針作為參數給一個方法後,你為猶豫我能不能施放這個指針。因為你不知道這個方法内部會不會将你的指針施放。

    于是有了誰擁有誰施放的施放管理思想。

    使用了上述管理機制和思想後,有些特定情況。比如方法内建立一個對象,然後傳回對象時,按照誰擁有誰施放。對象是在方法内部建立的,方法退出前不再擁有,是以要在方法退出前釋放。但是又要在退出時傳回該對象。先傳回還是先釋放都是不對的。。。

    于是就有了autorelease。

1、release 和retain是配套的,釋放管理是通過引用計數。

    每一個CCObject對象都有一個引用計數。retain()時引用計數+1,release()則-1.在release之後,若引用計數為0,便會調用delete this; 真正的釋放自己的記憶體。

    CCObject建立的時候,引用計數預設為1.

2、release和retain的使用的指導思想是,誰擁有誰施放。

    對于一個需要釋放的變量。他的生命中通過建立、傳遞參數、方法傳回值出現在各種地方,然而隻有有人需要長期存儲他的引用時,即想要擁有他,才應該調用retain()。釋放時則秉着“誰retain誰施放”,retain和release的調用次數要配套。

------------------------------------------------------

void class IhaveObjHandler()

{

public:

   ObjX* objHandler;

   static void iWantObjX(objX* o){ 

      objHandler = o;   // 位置2

      objHandler->retain();

   }

   IhaveObjHandler(){

      objHandler = NULL;

    }

   ~IhaveObjHandler(){

      if(objHandler != NULL){ objHanlder->release();}

}

void dispatchObjX(){

    ObjX* obj = new ObjX(); // 位置1

    IhaveObjHandler::iWantObjX( obj );

    obj->release();

示例中:需要釋放管理的對象是 ObjX , 他在位置1建立,在位置2被傳入到IhaveObjHandler。

位置1:因為obj建立時引用計數為1,而我(dispatchObjX方法)是不需要ObjX對象的,是以當我把他傳給IhaveObjHandler 之後,我便釋放他。

位置2:IhaveObjHandler裡需要儲存ObjX的引用,于是我(IhaveObjHandler類)調用retain()。當我不需要他,想要把他釋放的時候調用release().

在釋放的時候,注意自己retain幾次,隻能釋放幾次,不能過多釋放。

3、autoreleas是一個特殊的release,即延後釋放。

    對比上面的dispatchObjX方法

ObjX* createObjX(){

    ObjX* obj = new ObjX(); 

    obj->autorelease();   //位置3 如果改成 obj->release();則obj的引用計數為0,會被釋放。

    return obj;

    上面示例是一個産生新對象的方法。經常會用到,如果按照上述的釋放管理思想,如位置3的注釋寫的那樣。會在方法傳回之前被釋放。于是有了autorelease。

    autorelease其實隻是為obj設定一個标記,延後釋放。在之後的某一時刻,對obj的autorelease标記做處理(即釋放)。上面示例中autorelease不是立即減少obj引用計數,則方法可以安全return obj;。

4、autoRelease實作原理的小細節

    關鍵字CCAutoreleasePool

    autorelease的對象會加入到從池中,最遲會在每個主循環結束前釋放。

    池是用棧形式管理的。在适當情況下建立一個自動釋放池,加入到棧中。所有要釋放的對象都會加入到目前棧頂的這個池中,在特定情況(如每次主循環結束前),将池出棧。出棧時,做一些釋放池中對象的處理。

    當CCObject釋放時,如果該對象仍在自動釋放池中,則從池中删除自己。

    同一個對象多次autorelease()的話,會被多次加入池中。池中對象存儲結構是CCMutableArray,也就是vector.

5、 使用autorelease的好處

    1、new出來的對象的釋放問題解決了。符合誰擁有誰釋放的原則。

    2、可以避免頻繁申請/釋放記憶體 //ttun注:(沒想出來,是什麼意思)

6、其實autorelease并沒有那麼好用

    綜上,autorelease隻不過解決了前言中及第三條說的引用計數的那個使用上的問題。對于引用計數本質沒有太大改變。

    我們依舊要很小心小心小心的注意釋放對象的引用計數的變化。如果引用計數亂了一個的話,會導緻報錯。而且一旦因引用報錯後,一般情況你是無法立即知道是哪裡的引用除了問題。

    另外,使用了引用計數的話,釋放對象時别用delete, 而使用release()。

作者:newcj

出處:http://newcj.cnblogs.com/

歡迎轉載,但還請尊重勞動果實,保留此段聲明并注明原文連結。

繼續閱讀