cocos2d-x源码中的内存管理

来源:互联网 发布:穆斯林 知乎 编辑:程序博客网 时间:2024/06/15 22:47

cocos2d-x的内存管理原则——引用计数机制

内存管理:引用计数机制, 当一个对象执行retain操作的时候,引用计数加1,当执行release操作的时候,引用计数减1,当引用计数为0时,此对象被释放。

通过基类Ref的代码实现,便可以明白基本的内存管理机制,直接打开 CCRef.cpp文件

//  我们直接来看看CCRef.cpp文件Ref::Ref(): _referenceCount(1)  //注:当Ref对象被创建,此对象的引用计数为1void Ref::retain()    //retain方法{    CCASSERT(_referenceCount > 0, "reference count should be greater than 0");    ++_referenceCount;  //引用计数加1}void Ref::release()   //release方法{    CCASSERT(_referenceCount > 0, "reference count should be greater than 0");    --_referenceCount;  //引用计数减1    if (_referenceCount == 0) //当引用计数为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; //删除对象!!!    }}Ref* Ref::autorelease()  //autorelease方法{    PoolManager::getInstance()->getCurrentPool()->addObject(this);   //将对象加入到自动释放池中    return this;}unsigned int Ref::getReferenceCount() const{    return _referenceCount;  //获取引用计数个数}

通过看Ref类的源码,可以得出结论:

1.当一个对象被创建的时候,将此对象的引用计数设置为12.当执行一次retain,引用计数加1,3.执行一次release,引用计数减14.当引用计数为0的时候,此对象被释放delete

Ref的autorelease方法

Ref* Ref::autorelease()  //autorelease方法{    PoolManager::getInstance()->getCurrentPool()->addObject(this);   //将对象加入到自动释放池中    return this;}

什么时候调用autorelease方法?

    Label* Label::create()    {        auto ret = new (std::nothrow) Label;        if (ret)        {            ret->autorelease();  //create函数里,会自动执行autorelease方法        }        return ret;    }

可以看出,在create函数里,会自动执行autorelease方法, 也就是加入到自动释放池

AutoreleasePool 自动释放池:

它有个属性_managedObjectArray,可以将执行了autorelease方法的Ref对象加入_managedObjectArray,当AutoreleasePool::clear()时,也就是对_managedObjectArray中的每一项执行release操作

PoolManager 自动释放池管理类

有个生成器属性_releasePoolStack,里面加入的都是AutoreleasePool的对象,可以获取当前的AutoreleasePool

可以看到实现是建立了一个PoolManager的单例,接下来看看PoolManager,有个生成器属性_releasePoolStack

PoolManager* PoolManager::s_singleInstance = nullptr;PoolManager* PoolManager::getInstance(){  //PoolManager是个单例    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* PoolManager::getCurrentPool() const{    return _releasePoolStack.back(); //_releasePoolStack最后的一个AutoreleasePool对象}//注意接下来的两个函数:push,popvoid PoolManager::push(AutoreleasePool *pool){    _releasePoolStack.push_back(pool); //在_releasePoolStack这个vector尾部加入pool}void PoolManager::pop(){    CC_ASSERT(!_releasePoolStack.empty());    _releasePoolStack.pop_back();//删除_releasePoolStack最后一个元素}

PoolManager::getInstance()->getCurrentPool()->addObject(this)中的getCurrentPool可以看出获取到了一个AutoreleasePool对象,然后我们查看AutoreleasePool

class CC_DLL AutoreleasePool{   private:    std::vector<Ref*> _managedObjectArray;   //AutoreleasePool有个生成器属性_managedObjectArray,用来装Ref对象};void AutoreleasePool::addObject(Ref* object){    _managedObjectArray.push_back(object);}void AutoreleasePool::clear() //清楚操作{#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)    _isClearing = true;#endif    std::vector<Ref*> releasings;    releasings.swap(_managedObjectArray);  //遍历_managedObjectArray,为每一个对象执行release操作    for (const auto &obj : releasings)    {        obj->release();    }#if defined(COCOS2D_DEBUG) && (COCOS2D_DEBUG > 0)    _isClearing = false;#endif}

PoolManager::getInstance()->getCurrentPool()->addObject(this)中的addObject其实就是给_managedObjectArray这个vector中添加一个Ref对象

可以看到AutoreleasePool::clear()的方法实现,其实是把_managedObjectArray里面的每一个对象执行一次release操作,clear函数会在DisplayLinkDirector的mainLoop函数中被调用,一帧调用一次,及时回收。

void DisplayLinkDirector::mainLoop(){    if (_purgeDirectorInNextLoop)    {        _purgeDirectorInNextLoop = false;        purgeDirector();    }    else if (_restartDirectorInNextLoop)    {        _restartDirectorInNextLoop = false;        restartDirector();    }    else if (! _invalid)    {        drawScene();        // release the objects !!!在此处执行clear操作        PoolManager::getInstance()->getCurrentPool()->clear();    }}

总结一下就是内存管理的源代码实现:

常见的label,button等对象在执行create()函数的时候,会自动执行autorelease()方法,就是将对象添加到AutoreleasePool的_managedObjectArray中,而在游戏中每一帧都会调用通过PoolManager获取到当前的AutoreleasePool对象,然后执行AutoreleasePool::clear()方法,给_managedObjectArray中的每一个对象执行release操作。

原创粉丝点击