在cocos2dx框架中,我們似乎有一種感覺–不用手動釋放記憶體,其實,這些都是框架幫我們實現好的
cocos2dx中採用了一種比較古老的方式—–引用計數的方式來實現記憶體的自動**,如果是了解c++11中的std::shared_ptr的同學肯定不會覺得陌生,原理是類似的。
我們首先來明確乙個問題,cocos2dx是在什麼地方釋放記憶體的呢?
我們來看原始碼:
ccdirector.cpp
//簡化版
void displaylinkdirector::mainloop()
這個是cocos2dx的主迴圈,我們不難看出,在每一幀繪製結束後,poolmanager
就會進行乙個clear()
操作,這裡,就是我們cocos2dx記憶體管理的入口了
那麼這個poolmanager
又是怎麼實現的呢?
這個就要從我們ref
類講起了
class cc_dll ref
根據我們上面主迴圈的**poolmanager
應該是實現記憶體自動釋放的關鍵
class cc_dll poolmanager
...autoreleasepool* poolmanager::getcurrentpool() const
這是乙個單例類,其中呼叫的getcurrentpool
方法返回的只是乙個autoreleasepool
的向量
並且這個autoreleasepool
是他的友緣類,而且也是ref
的友緣類
我們來看看autoreleasepool
的實現
class cc_dll autoreleasepool
void autoreleasepool::clear()
...}
ref::relase的實現
void ref::release()
...}
大體上就是這樣乙個流程
那麼如何保留我們的例項不被釋放呢?
很簡單,使用我們的retain
方法,其實就是將引用計數加一
void ref::retain()
因為每次進行clear()
的時候,會把_managedobjectarray
清空
也就是說,每個繼承自ref
的類例項化後只會進行一次release
,所以我們呼叫retain
將引用計數加一後就不用擔心被釋放的問題了
那麼reatin
後的例項如何釋放呢?
也很簡單, 呼叫autorelease
或者release
即可
ref* ref::autorelease()
void
autoreleasepool::addobject(ref* object)
autorelease
會將當前例項加入到待釋放陣列中,所以就可以實現自動釋放了
還有乙個問題,既然是引用計數,那麼最開始的引用數是在**賦值的呢?
是在ref
的建構函式中
ref::ref()
: _referencecount(1) // when the ref is created, the reference count of it is 1
...
所以,我們在cocos2dx開發中,一般使用框架中的vector
因為vector
在pushback()
的時候,會呼叫一次retain
官方文件上的一些話:
ccautoreleasepool不能被開發者自己建立。cocos2d-x會為我們每乙個遊戲建立乙個自動釋放池例項物件,遊戲開發者不能新建自動釋放池,僅僅需要專注於release/retain cocos2d::ccobject的物件。ccautoreleasepool不能被用在多執行緒中,所以假如你遊戲需要網路執行緒,請僅僅在網路執行緒中接收資料,改變狀態標誌,不要這個執行緒裡面呼叫cocos2d介面。下面就是原因:
ccautoreleasepool的邏輯是,當你呼叫object->autorelease(),object就被放到自動釋放池中。自動釋放池能夠幫助你保持這個object的生命週期,直到當前訊息迴圈的結束。在這個訊息迴圈的最後,假如這個object沒有被其他類或容器retain過,那麼它將自動釋放掉。例如,layer->addchild(sprite),這個sprite增加到這個layer的子節點列表中,他的宣告週期就會持續到這個layer釋放的時候,而不會在當前訊息迴圈的最後被釋放掉。
這就是為什麼你不能在網路線層中管理ccobject生命週期,因為在每乙個ui執行緒的最後 ,自動釋放物件將會被刪除,所以當你呼叫這些被刪掉的物件的時候,你就會遇到crash。
簡而言之,這只有兩種情況你需要呼叫release()方法
你new乙個cocos2d::ccobject子類的物件,例如ccsprite,cclayer等。
你得到cocos2d::ccobject子類物件的指標,然後在你的**中呼叫過retain方法。
cocos2d x 原始碼剖析(2)
上次講到cocos2d x的main loop是下面這句 我們來看看這個函式的內部實現 return0 看看,我沒有欺騙大家吧。這個函式在設計的時候想要參照main函式返回乙個int值來表示執行結果,但是你知道的外部呼叫中完全沒有進行處理,略坑爹。來深入這個函式的內部 void startmainl...
cocos2d x 原始碼剖析(1)
原文出處 我認為在看這些文章的時候,最好有一些cocos2d x的經驗。起碼能新建乙個cocos2d x的hello world工程。而且這些文章並不是用來入門和教你如何使用cocos2d x的,我的目標是看完這些文章之後,寫乙個完整的2d引擎將沒有問題。而且能夠為cocos2d x查漏補缺,看看那...
cocos2d x 原始碼剖析(8)
寫到第7節的時候,突然覺得cocos2d x還沒有我想的那麼大啊,或許在50節以內就要了結了。這節繼續看看ccnode這個節點,主要部分是action。雖然ccnode有不少的action相關的函式,起作用的實際上是actionmanager。這節雖說是從ccnode開始,但是真正的內容在actio...