![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-YWan5SOmlTZkRDOhV2Y5gDMiRjMwYDN4cDM4YDZiNTMzgTMy8CXxAzLchDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL0M3Lc9CX6MHc0RHaiojIsJye.gif)
再來一彈,記憶體管理機制
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsISPrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdsATOfd3bkFGazxCMx8VesATMfhHLlN3XnxCMwEzX0xiRGZkRGZ0Xy9GbvNGLpZTY1EmMZVDUSFTU4VFRR9Fd4VGdsYTMfVmepNHLrJXYtJXZ0F2dvwVZnFWbp1zczV2YvJHctM3cv1Ce-YWan5SOmlTZkRDOhV2Y5gDMiRjMwYDN4cDM4YDZiNTMzgTMy8CXxAzLchDMxIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjL0M3Lc9CX6MHc0RHaiojIsJye.gif)
1.簡言機制
2.代碼觀機制
1.簡言-Cocos2d-x的記憶體管理機制
說到記憶體管理,這是個question,(⊙v⊙)嗯。。
看一下各語言怎麼進行記憶體管理吧?
——JAVA:
堆區的就是new來配置設定記憶體。通過垃圾回收機制來回收。
(詳細的非常複雜,能夠看看這個文章 -> javascript:void(0) )
——C++:
new來建立,delete來删除
——Objective-C:
採用引用計數的方法
建立一個Obj,每一個Obj都有一個retainCount。
在new、alloc、retain的時候,都會讓這個retainCount+1。
若對這個對象,進行release操作,則會讓retainCount-1。
是以。每一個對象都有兩個方法:retain和release。
當retainCount為0時,這個對象就被釋放了。
而Cocos2d-x 使用C++實作了Objective-C的管理機制。
2.代碼觀-cocos2d-x的記憶體管理機制
建立一個對象,來看看一看這個管理機制。
打開項目,在入口程式AppDelegate.cpp中能夠看到:
// create a scene. it's an autorelease object
auto scene = HelloWorld::createScene();
// run
director->runWithScene(scene);
建立了一個場景。并執行。跟蹤進去。建立場景的函數:
// 'scene' is an autorelease object
auto scene = Scene::create();
// 'layer' is an autorelease object
auto layer = HelloWorld::create();
在createScene函數中。進行了場景的建立和圖層的建立。
都用的是create方法。不管是scene還是layer,它們都是屬于node子類。相同node也是ref的子類。
之前說過,Ref類就是cocos2d-x的記憶體管理機制。
跟蹤到,Ref類,能夠發現:
<span style="font-size:14px;">class CC_DLL Ref
{
public:
/**
* Retains the ownership.
*
* This increases the Ref's reference count.
*
* @see release, autorelease
* @js NA
*/
void retain();
/**
* Release the ownership immediately.
*
* This decrements the Ref's reference count.
*
* If the reference count reaches 0 after the descrement, this Ref is
* destructed.
*
* @see retain, autorelease
* @js NA
*/
void release();
/**
* Release the ownership sometime soon automatically.
*
* This descrements the Ref's reference count at the end of current
* autorelease pool block.
*
* If the reference count reaches 0 after the descrement, this Ref is
* destructed.
*
* @returns The Ref itself.
*
* @see AutoreleasePool, retain, release
* @js NA
* @lua NA
*/
Ref* autorelease();
/**
* Returns the Ref's current reference count.
*
* @returns The Ref's reference count.
* @js NA
*/
unsigned int getReferenceCount() const;
protected:
/**
* Constructor
*
* The Ref's reference count is 1 after construction.
* @js NA
*/
Ref();
public:
/**
* @js NA
* @lua NA
*/
virtual ~Ref();
protected:
/// count of references
unsigned int _referenceCount;
friend class AutoreleasePool;
#if CC_ENABLE_SCRIPT_BINDING
public:
/// object id, ScriptSupport need public _ID
unsigned int _ID;
/// Lua reference id
int _luaID;
#endif
};
</span>
。。。。。 好長
裡面有:
retain方法(添加引用),
release方法(降低引用),
autorelease方法(實作自己主動釋放)
getReferenceCount方法(獲得引用計數)
Ref(),~Ref() 構造函數和析構函數
_referenceCount這個就是引用值
AutoreleasePaul友元類
_ID,_luaID對JS和Lua腳本的支援
再看一下,這個類的詳細定義,
能夠在項目目錄内的:cocos2d/cocos/base/找到Ref類
也能夠在,VS2012打開後。外部依賴項裡找Ref類,但找到的都是.h頭檔案。我們要看的.cpp喲
可是,這個類找的時候,叫CCRef
——在,Ref構造函數能夠看到:
Ref::Ref()
: _referenceCount(1) // when the Ref is created, the reference count of it is 1
也就是說,每當建立一個對象,它的引用值初始化為1。
——當,運作retain方法
void Ref::retain()
{
CCASSERT(_referenceCount > 0, "reference count should greater than 0");
++_referenceCount;
}
會對引用值++
——當,運作release方法
void Ref::release()
{
CCASSERT(_referenceCount > 0, "reference count should greater than 0");
--_referenceCount;
會對引用值--
——且,release後,要進行是否為0的推斷,若為0,則delete this:
if (_referenceCount == 0)
{
#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
auto poolManager = PoolManager::getInstance();
if (!poolManager->getCurrentPool()->isClearing() && poolManager->isObjectInPools(this))
{
CCASSERT(false, "The reference shouldn't be 0 because it is still in autorelease pool.");
}
#endif
delete this;
}
從此可見,cocos2d-x是通過引用計數來控制對象的生命周期。
是以。cocos2d-x程式設計時。基本不用delete語句,僅僅有在非Ref基類的類或者Ref類内才會用delete語句。
再回過頭,看一下Scene的create方法:
Scene *Scene::create()
{
Scene *ret = new Scene();
if (ret && ret->init())
{
ret->autorelease();
return ret;
}
else
{
CC_SAFE_DELETE(ret);
return nullptr;
}
}
在這裡面,我們先建立場景,然後運作場景初始化方法(init)。然後把目前對象加入到自己主動釋放池管理,
這種方法定義:
Ref* Ref::autorelease()
{
PoolManager::getInstance()->getCurrentPool()->addObject(this);
return this;
}
這樣一來,我們就不須要自己明白的編碼。并且當對象被引用,自己主動進行release方法。
——end
恩,就到這裡了,本來想用執行個體來執行一下,可出了些問題。
明天就要走了。有段時間不能上了。唉。。
參考資料:
sdhjob(沈老師)