原文來自:http://blog.csdn.net/a7833756/article/details/7628328
這篇文章寫得很詳細..
前言:c++記憶體機制,採用new關鍵字執行個體化的對象,必須在不使用的時候手動delete掉,否則new的時候開闢的記憶體就不能被回收,造成記憶體泄露。
我們來舉個例子說明一下:
運行 結果,vld工具提示了存在記憶體泄露:
當加上delete操作後:
下面步入正題:
1、cocos2d-x 記憶體管理的方式,cocos2d-x採用引用計數的方式進行記憶體管理,當一個對象的引用計數為0的時候,就會被引擎自動delete掉。
所有cocos2d-x裡面的類都繼承ccobject類(應該是吧、),下面看ccobject類源碼:
這裡 m_uReference 就是引用計數,在物件建構的時候,m_uReference置為1
然後每次對對象進行retain操作,reference+1
每次對對象進行release操作,reference-1,如果reference在這次release之後變為0,那麼delete掉它
2、以上是記憶體管理的基本原則,下面來講引擎中是怎麼對對象進行自動管理(autorelease)的。
我們以一個CCNode的生命曆程為例,來講一下自動管理的整個過程:
首先建立一個CCNode:
CCNode對象被new出來之後,立刻執行autorelease操作,我們來進行跟蹤:
可以看到,首先將m_bManaged置為true,表示處於自動管理狀態,然後加入自動管理池,繼續跟蹤:
getCurReleasePool() 返回一個 CCAutoreleasePool 對象指標,也就是一個自動釋放池,那麼我們先去看看這個自動釋放池裡面有什麼:
首先就是一個ccobject數組,m_pManagedObjectArray , 這個數組放的就是接受自動釋放的對象,也就是說,進行autorelease的對象,最終被放到它裡面去了
那我們注意一下這裡,m_pManagedObjectArray 是一個 CCMutableArray 對象,它的addobject()方法除了把一個對象放到這個array裡面去,還做了什麼呢,我們來看看源碼:
大家應該看到了,進行了一次retain()操作,使得對象的引用+1,那麼對象在被add到這個array裡之後,引用應該為2(不考慮其他地方進行的retain),所以在此之後立刻進行了一次release(),使得這次add造成的引用取消,這樣一來,對象從建立開始引用為1,到現在被放進自動釋放池中後,引用依然為1,同時,被管理狀態為true。
那麼我再進行深入的分析一下
getCurReleasePool()->addObject(pObject);
裡面的getCurReleasePool()方法,注意這個方法是 CCPoolManager 的方法:
那麼我看到 CCPoolManager 類,顧名思義,我們也想得到它是對自動釋放池進行管理的類,這是個全域變數,在main()函數執行之前由系統自動調用其預設構造方法進行執行個體化。下面進入這個類去看看裡面有些什麼:
我們發現了,裡面有一個 CCAutoreleasePool 對象 m_pCurReleasePool, 看它名字, 可以理解為 當前自動釋放池 ,然後有一個記憶體池的數組 m_pReleasePoolStack ,裡面放的就是多個記憶體釋放池了(我好像就看到一個進去了)。那麼我們連上剛才的思路,進去看看push()函數,做了什麼事情:
如代碼所示,push()操作new了一個自動釋放池對象,並且將它賦值給 當前自動釋放池(m_pCurReleasePool),然後將這個new的自動釋放池對象放到CCPoolManager 裡面的 釋放池數組中。注意過程中對其引用計數的控制,自動釋放池本身也是繼承ccobject的,也有自己的引用計數,受相同的記憶體管理方式。
那麼到這裡,一個對象的autorelease()過程就完成了。
那麼我來做一個簡單的總結:
首先 new 一個對象, 然後執行其autorelease()方法,接下來是得到CCPoolManager 對象(這是一個全域的對象),用它的getCurReleasePool擷取 當前自動釋放池對象,並將這個new的對象放入 當前自動釋放池對象 裡面的m_pManagedObjectArray數組中,修改其被管理狀態 m_bManaged 為 true。執行完這個完整的操作之後,這個新new出來的對象的引用次數為1,被管理狀態為true,並且被放在一個管理對象的數組中。
先理解自動釋放池的添加過程,並且搞清楚對象被添加前後之間的變化,然後下一篇,來講被自動管理的對象是如何被引擎自動刪除的。