1.1.01_COCOS2D-X内存管理机制

2017-07-04  本文已影响18人  资深小夏

Cocos2d-x 的内存管理方法基于 Cocos2d-iPhone 的 Objective-C 风格的内存管理,把 Objective-C 的内存管理方式引入 C++。

1 复杂的内存管理

C++设计上不包含任何智能管理内存的机制,所以开发过程中需要考虑如何管理内存,包括:

内存管理的核心是动态分配的对象必须保证在使用完毕后有效地释放内存,即管理对象的生命周期

2 现有的智能内存管理技术

目前,主要有两种实现智能管理内存的技术,一是引用计数,一是垃圾回收

3 Cocos2d-x的内存管理机制

Cocos2d-x采用了引用计数与自动回收的内存管理机制

    /**
     * Retains the ownership.
     *
     * This increases the Ref's reference count.
     *
     * @see release, autorelease
     * @js NA
     */
    void retain();

    /**
     * Releases the ownership immediately.
     *
     * This decrements the Ref's reference count.
     *
     * If the reference count reaches 0 after the decrement, this Ref is
     * destructed.
     *
     * @see retain, autorelease
     * @js NA
     */
    void release();

    /**
     * Releases the ownership sometime soon automatically.
     *
     * This decrements the Ref's reference count at the end of current
     * autorelease pool block.
     *
     * If the reference count reaches 0 after the decrement, 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;
PoolManager* PoolManager::getInstance()
{
    if (s_singleInstance == nullptr)
    {
        s_singleInstance = new (std::nothrow) PoolManager();
        // Add the first auto release pool
        new AutoreleasePool("cocos2d autorelease pool");
    }
    return s_singleInstance;
}
AutoreleasePool::AutoreleasePool(const std::string &name)
: _name(name)
#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)
, _isClearing(false)
#endif
{
    _managedObjectArray.reserve(150);
    PoolManager::getInstance()->push(this);
}
void Director::mainLoop()
{
    if (_purgeDirectorInNextLoop)
    {
        _purgeDirectorInNextLoop = false;
        purgeDirector();
    }
    else if (_restartDirectorInNextLoop)
    {
        _restartDirectorInNextLoop = false;
        restartDirector();
    }
    else if (! _invalid)
    {
        drawScene();
     
        // release the objects
        PoolManager::getInstance()->getCurrentPool()->clear();
    }
}

4 工厂方法

工厂方法是程序设计中一个经典的设计模式,指的是基类中只定义创建对象的接口,将实际的实现推迟到子类中。在这里, 我们将它稍加推广,泛指一切生成并返回一个对象的静态函数。一个经典的工厂方法如同这样:

CCObject* factoryMethod()
{
    CCObject* ret = new CCObject();
 }

//在这里对 ret 对象进行必要的初始化操作 return ret;
这段看起来正常的代码其实隐藏着一个问题:工厂方法对ret对象的引用在函数返回时已经结束,但是它没有释放对ret 的引用,埋下了内存泄露的隐患。但是,如果在函数返回前就执行 release(),这显然是不合适的,因为这会触发对象的回 收,再返回的对象指针就成为了错误指针。
autorelease()方法很好地解决了回收池中的对象不会在使用完毕前释放。利用 autorelease()修改后的工厂方法如下:

CCObject* factoryMethod()
{
    CCObject* ret = new CCObject(); //这里对 ret 对象进行必要的初始化操作
    ret->autorelease();
    return ret;
} 

5 关于对象传值

对象赋值给某一指针作为引用的时,需要获得新对象的引用权,释放旧对象的引用权。此时,release()和 retain()的顺序是尤为重要的。首先来看下面一段代码:

void SomeClass::setObject(CCObject* other)
{ 
    this->object->release();
    other->retain();
    this->object = other;
}

6 释放:release()还是autorelease()?

上一篇 下一篇

猜你喜欢

热点阅读