cocos2dx 記憶體管理

2021-07-16 15:16:41 字數 2569 閱讀 4479

我們知道,cocos2dx中使用了引用計數的方式去管理記憶體,不需要我們手動delete的去釋放記憶體。那麼cocos2dx中是怎麼實現引用計數的記憶體管理方式的呢?

cocos2dx中的記憶體管理用到了兩個工具:引用計數器(ref)、自動**池(autoreleasepool)。

引用計數器(ref):

①ref成員變數_referencecount:引用計數,用來記錄物件被引用的次數。

②retain函式:使引用計數加1。

③release函式:使引用計數減1,並當引用計數為0時**物件。

④autorelease函式:將物件加入到自動**池。要使用cocos2dx的自動**池必須使用該方法。

由以上幾點我們可知,要使用cocos2dx的記憶體管理機制,我們必須繼承ref類(如scene、layer、sprite等)並呼叫autorelease函式。

自動**池(autoreleasepool):

_managedobjectarray,autoreleasepool的成員變數。它的型別是vector,用來管理新增到自動**池中的物件。物件呼叫autorelease函式就把該物件新增到_managedobjectarray中。在遊戲主迴圈中,cocos2dx每一幀遍歷_managedobjectarray中的物件,並使它們都呼叫release函式。

小夥伴可能會問了:每一楨都呼叫release函式,那所有的物件不是都會很快被**掉麼。答案是否定的。因為每一幀_managedobjectarray都會被清空。我們在建立物件時呼叫autorelease函式(一般用法,特殊用法我們這裡不討論),那麼我們建立物件這個操作算作該物件的一次引用,而這個引用的生命週期僅僅是在我們建立物件語句所在的大括號裡面。所以自動**池要在下一幀**這個引用。而我們要**建立物件以後對該物件的引用,就要通過手動的呼叫release函式或者通過呼叫其它在內部呼叫了release函式的函式(一般cocos2dx內部自動release不需我們手動呼叫)。

下面我們通過幾段**來具體認識一下

sprite* sp = nullptr;

bool lgamescene::init()

void lgamescene::func(float delt)

我們有個全域性變數sp,在init函式裡使用create對它進行初始化。並且我們使用了scheduleonce在2秒後呼叫func函式設定sp的position。執行結果如下:

報錯了。這是為什麼呢?

在cocos2dx中使用create方法會在內部呼叫autorelease函式。也就是說,在init方法中建立了sprite物件sp之後,自動**池會馬上讓該物件呼叫release函式,這時這個物件的引用計數(初始化為1)會馬上變成0,馬上被release清理掉。這意味著這個物件建立之後馬上被銷毀了,所以在func中再使用它就出錯了。

下面我們修改init方法如下:

bool lgamescene::init()

我們加了一行**:sp->retain();這時,我們的引用計數加1變為2。自動**池使sp->release之後sp的引用計數為1,不被**。所以這時執行不報錯了。

問題:cocos2dx中當節點被**時,它的子節點的**是在**實現的?

乙個節點要變為另乙個節點的子節點那麼必然會呼叫addchild函式。在addchild函式內部呼叫了retain函式使節點不會被自動**池**。所以經過addchild和自動**池後,子節點的引用計數為1(我們沒有手動呼叫retain函式的情況下。如果呼叫了retain要及時呼叫release,否則節點將不被自動**。),那麼這時,我們要**子節點只需讓子節點呼叫一次release函式即可。

那麼,結合上面的知識,我們很容易知道,我們只要在父節點**時遍歷子節點並讓子節點呼叫release函式即可,即乙個迴圈結構。break檢視原始碼發現,node::removeallchildren函式內部有這個遍歷**過程。然後break找到node的析構函式,發現析構函式內部即沒有呼叫removeallchildren又沒有剛才提到的迴圈結構。

最後,break注意到node的成員變數 vector_children。_children中儲存了所有的子節點,要遍歷子節點離不開_children。而node析構時會隱式呼叫vector的析構方法來清除_children。而這個vector是cocos2dx自帶的,並不是c++ stl中的vector。於是,break找到vector的析構函式,發現它在內部呼叫了clear函式,clear函式**如下:

void clear()

_data.clear();

}

!!!子節點的遍歷**就在裡了有木有!!!隱藏的好深有木有!

cocos2dx 記憶體管理

記憶體管理中經常遇到的問題 記憶體洩露,記憶體溢位。在cocos2dx中用的是引用計數和自動釋放池的技術,由於熟悉objective c語言,所以對這兩個概念不會很陌生。一 引用計數 引用計數是自動記憶體管理的基礎 在物件裡增加乙個引用計數,當外部引用增加時,計數器加1,當外部引用消失時,計數器減1...

cocos2d x 記憶體管理

呼叫了autorelease的物件,將會在自動 池釋放的時候被釋放一次。因為這個操作發生在 mainloop drawscene 後,這時候遊戲中所有的邏輯已經執行完畢,正是釋放無效資源的最佳時機。所以乙個物件被create後,將被放進pool中,其ref 數為1,當遊戲整個邏輯跑完,如果沒有增加r...

Cocos2d x 記憶體管理

一 記憶體管理機制 cocos2d x是一套基於c 的引擎,c 的記憶體機制,如果採用new關鍵字宣告乙個物件而沒有手動delete掉,那麼申請的記憶體就不會被 進而造成記憶體洩露。cocos2d x是採用引用計數的方式管理記憶體,基本的原則就是當構造乙個物件時,引用計數為1,每次進行retain操...