Cocos2d-x 内存管理与数据结构

Cocos2d-x 内存管理与数据结构

引用计数

Cocos采用的是引用计数的方式管理内存,Cocos会记录堆上每个对象被引用的次数,当引用次数为0时则自动释放内存。

 

Ref

为了实现对类引用次数的管理,Cocos的类都继承了Ref类。

class CC_DLLRef
{
public:
    voidretain();  //增加引用计数,当需要保存使用对象时,需要调用该函数增加引用计数
    voidrelease(); //减少引用计数,当引用计数减少到0时则时会释放内存
    Ref*autorelease(); //将内存加入自动释放内存池,下一次Application::run()的循环会调用一次对象的Release函数
    unsignedintgetReferenceCount() const;//获取引用次数
    virtual~Ref();  //虚析构函数保证派生类的析构函数被调用到
protected:
    Ref();//将构造函数设为保护属性,就无法直接实例化Ref类,new Ref()将报错
protected:
    unsignedint_referenceCount;//记录引用的次数
    friendclassAutoreleasePool;
};



AutoreleasePool

为了实现内存的自动释放AutoreleasePool创建了内存池,内存池会记录所有要自动释放的内存。

class CC_DLLAutoreleasePool
{
public:
    AutoreleasePool();
    AutoreleasePool(conststd::string&name);
    ~AutoreleasePool();
    void addObject(Ref *object);//将对象加入到自动管理内存池
    voidclear(); //清理内存
    boolcontains(Ref* object)const;//对象是否在内存池中
    voiddump(); //将内存池中的内对象信息输出到日子,方便调试
    
private:
    std::vector<Ref*>_managedObjectArray;
    std::string_name;
    
};

AutoreleasePool内存的释放

Main函数调用的Run函数的循环调用了director->mainLoop(),其每次绘制完后会清理内存

void DisplayLinkDirector::mainLoop()
{
    if(_purgeDirectorInNextLoop){
        _purgeDirectorInNextLoop= false;
        purgeDirector();
    }
    elseif(_restartDirectorInNextLoop){
        _restartDirectorInNextLoop= false;
        restartDirector();
    }
    elseif(! _invalid)
    {
        drawScene();
        //清理内存,对AutoreleasePool中的每个对象掉Ref::release函数
        PoolManager::getInstance()->getCurrentPool()->clear();
    }
}


 

引用内存的使用

new一个对象后引用计数为1,然后调用Ref::autorelease加入到自动管理内存池,对象会在下一次主循环时调用Ref::release如果需要保存对象一直使用则需要调用一次Ref::retain函数增加引用计数。例如:

//内部会调用 autorelease函数,create函数见下方代码
auto sprite = Sprite::create("HelloWorld.png"); 
this->addChild(sprite, 0);//内部会调用Ref::retain函数增加引用计数

Sprite* Sprite::create(const std::string& filename)
{
    Sprite *sprite = new (std::nothrow) Sprite();
    if (sprite && sprite->initWithFile(filename))
    {
        sprite->autorelease();
        return sprite;
    }
    CC_SAFE_DELETE(sprite);
    return nullptr;
}

 

         为了方便和统一create的定义函数,Cocos提供了相CREATE_FUNC宏,在类中加入该宏及定义了create函数。

#defineCREATE_FUNC(__TYPE__) \
static__TYPE__* create() \
{\
    __TYPE__ *pRet = new(std::nothrow)__TYPE__(); \
    if (pRet&& pRet->init()) \
    { \
        pRet->autorelease();\
        returnpRet; \
    } \
    else \
    { \
        deletepRet; \
        pRet = nullptr;\
        returnnullptr;\
    } \
}


         例如:

classHelloWorld: public cocos2d::Layer
{
public:
    virtual boolinit();
    void menuCloseCallback(cocos2d::Ref*pSender);
    //定义静态create函数
    CREATE_FUNC(HelloWorld)
};
    auto layer= HelloWorld::create();//CREATE_FUNC宏定义的函数
    scene->addChild(layer);

 

 

 

Vector

CocosVector类是对C++ STL中的std::vector进行了一层封装,其只有一个变量    std::vector<T>_data;之所以要重新封装一层,是为了实现对引用计数内存的管理。

当向_data数组中添加数据时其会对调用对象的Ref:: retain函数增加引用计数,从_data中删除数据时会调用Ref::release函数减少引用计数释放释放内存。

 

例如pushback函数和popBack函数

    voidpushBack(T object)
    {
        CCASSERT(object != nullptr,"The object should not be nullptr");
        _data.push_back( object );
        object->retain();//增加引用计数
    }
    voidpopBack()
    {
        CCASSERT(!_data.empty(), "no objects added");
        autolast= _data.back();
        _data.pop_back();
        last->release();//减少引用计数释放内存
    }

 

Map

cocos2d::Map类是使用std::unordered_map作为底层结构的关联式容器。在关联式容器的基础上进行封装实现对引用计数内存的自动管理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值