您的位置:首页 > 理论基础 > 数据结构算法

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

2017-01-21 21:33 267 查看
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类

Cocos中Vector类是对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作为底层结构的关联式容器。在关联式容器的基础上进行封装实现对引用计数内存的自动管理。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  C++ cocos2d-x