zoukankan      html  css  js  c++  java
  • 从零开始のcocos2dx生活(一)内存管理

    cocos中所有的对象都是继承自Ref基类,Ref的职责就是对对象进行引用计数管理

    内存管理中最重要的是三个方法retain()、release()、autorelease()

    在cocos中创建对象的标准流程是:
    创建对象->初始化->添加到自动内存管理->返回创建成功的对象
    就比如下面这段代码1:创建Node对象

    //代码1
    Node * Node::create()
    {
        Node * ret = new (std::nothrow) Node();
        if (ret && ret->init())
        {
            ret->autorelease();
        }
        else
        {
            CC_SAFE_DELETE(ret);
        }
        return ret;
    }
    

    在代码1中,我们只需要调用create方法就可以实现创建对象、初始化和自动管理内存。

    在cocos中有的函数中直接使用了create的宏定义,调用对象的create方法就可以执行代码2,实现的功能和代码1是一样的。

    //代码2
    #define CREATE_FUNC(__TYPE__) \
    static __TYPE__* create() \
    { \
        __TYPE__ *pRet = new(std::nothrow) __TYPE__(); \
        if (pRet && pRet->init()) \
        { \
            pRet->autorelease(); \
            return pRet; \
        } \
        else \
        { \
            delete pRet; \
            pRet = nullptr; \
            return nullptr; \
        } \
    }
    

    代码2中调用autorelease方法,将对象加入自动内存管理池自动管理。
    代码3是autorelease方法的实现

    //代码3
    Ref* Ref::autorelease()
    {
        PoolManager::getInstance()->getCurrentPool()->addObject(this);
        return this;
    }
    

    首先看一下代码4,PoolManager的getInstance方法
    在代码4中创建了PoolManager对象并调用了this的AutoreleasePool方法(代码5)
    "cocos2d autorelease pool"是这个自动管理池的name

    //代码4
    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;
    }
    

    在代码5中可以看到先是对_managedObjectArray预留空间,然后将this加了进去

    //代码5
    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);
    }
    

    在代码3中还调用了getCurrentPool方法用来获取当前的内存管理池

    //代码6
    AutoreleasePool* PoolManager::getCurrentPool() const
    {
        return _releasePoolStack.back();
    }
    

    然后把this加入到当前的内存管理池中作为一个ref对象进行管理,如代码7

    //代码7
    void AutoreleasePool::addObject(Ref* object)
    {
        _managedObjectArray.push_back(object);
    }
    

    整个流程如下图所示
    管理流程

    自动内存管理的结构如下图,用一个栈来存储多个自动内存管理池,在自动内存管理池中又有若干个ref对象。
    内存管理结构

    在内存管理中主要是靠引用计数来记录对象的使用情况,当一个对象被create时会给它分配内存,并且会调用retain()方法让引用计数+1;当调用release()时会让引用计数-1,release时会检查引用计数是否为0,引用计数为0时会调用delete删除对象并释放内存。

    在每一帧结束时会清理当前的内存管理池,将每一个ref对象的引用计数都-1,这帧结束之后,内存管理池中就没有这个ref对象了,引用计数是ref自己的属性,当下一次被release时如果引用计数=0,就会被释放。

    void Director::mainLoop()
    {
    	......
        PoolManager::getInstance()->getCurrentPool()->clear();
        }
    }
    void AutoreleasePool::clear()
    {
        std::vector<Ref*> releasings;
        releasings.swap(_managedObjectArray);
        for (const auto &obj : releasings)
        {
            obj->release();
        }
    }
    

    retain()和release()只是帮助我们记录一个对象的引用次数,在程序中几乎不用手动调用。

  • 相关阅读:
    单例模式
    HashSet、LinkedHashSet、SortedSet、TreeSet
    ArrayList、LinkedList、CopyOnWriteArrayList
    HashMap、Hashtable、LinkedHashMap
    andrew ng machine learning week8 非监督学习
    andrew ng machine learning week7 支持向量机
    andrew ng machine learning week6 机器学习算法理论
    andrew ng machine learning week5 神经网络
    andrew ng machine learning week4 神经网络
    vue组件监听属性变化watch方法报[Vue warn]: Method "watch" has type "object" in the component definition. Did you reference the function correctly?
  • 原文地址:https://www.cnblogs.com/sakuraneo/p/11992054.html
Copyright © 2011-2022 走看看