天天看點

cocos2d-x 3.0 記憶體管理機制

cocos2d-x 3.0 記憶體管理機制

再來一彈,記憶體管理機制

cocos2d-x 3.0 記憶體管理機制

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的管理機制。

cocos2d-x 3.0 記憶體管理機制

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>      

               。。。。。 好長

cocos2d-x 3.0 記憶體管理機制

裡面有:

retain方法(添加引用),

release方法(降低引用),

autorelease方法(實作自己主動釋放)

getReferenceCount方法(獲得引用計數)

Ref(),~Ref()  構造函數和析構函數

_referenceCount這個就是引用值

AutoreleasePaul友元類

_ID,_luaID對JS和Lua腳本的支援

再看一下,這個類的詳細定義,

cocos2d-x 3.0 記憶體管理機制

能夠在項目目錄内的: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語句。

cocos2d-x 3.0 記憶體管理機制

再回過頭,看一下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

恩,就到這裡了,本來想用執行個體來執行一下,可出了些問題。

明天就要走了。有段時間不能上了。唉。。

cocos2d-x 3.0 記憶體管理機制
cocos2d-x 3.0 記憶體管理機制

參考資料:

​​sdhjob(沈老師)​​

繼續閱讀