cocos2d-x 内存管理机制

cocos2d-x 内存管理机制,第1张

概述转自:http://www.2cto.com/kf/201403/284698.html 参考:http://blog.leafsoar.com/archives/2013/05-29.html http://blog.leafsoar.com/archives/2013/05-22.html http://blog.leafsoar.com/archives/2013/06-04.html 1.

转自:http://www.2cto.com/kf/201403/284698.html

参考:http://blog.leafsoar.com/archives/2013/05-29.html

http://blog.leafsoar.com/archives/2013/05-22.html

http://blog.leafsoar.com/archives/2013/06-04.html

1.引用计数机制

要了解cocos2dx引用计数的机制,首先我们来看看CCObject这个类


class CC_DLL CCObject : public CCcopying{public:    // object ID,ccScriptSupport need public m_uID    unsigned int        m_uID;    // Lua reference ID    int                 m_nLuaID;protected:    // count of references    unsigned int        m_uReference;    // count of autorelease    unsigned int        m_uautoReleaseCount;public:    CCObject(voID);    /**     *  @lua NA     */    virtual ~CCObject(voID);        voID release(voID);    voID retain(voID);    CCObject* autorelease(voID);    CCObject* copy(voID);    bool isSingleReference(voID) const;    unsigned int retainCount(voID) const;    virtual bool isEqual(const CCObject* pObject);    virtual voID acceptVisitor(CcdataVisitor &visitor);    virtual voID update(float dt) {CC_UNUSED_ParaM(dt);};        frIEnd class CCautoreleasePool;};


说明:

● 当m_uReference=0时会自动释放该对象,每引用一次对象的时候,m_uReference会+1,当object被创建,会初始化为1.

● 当m_uautoReleaseCount !=0时表示该对象自动释放(autorelease)。

●voID retain(voID) 对m_uReference+1 *** 作,可以防止对象被释放

●retainCount() 返回m_uReference值


● 跟踪一下voID release()方法,我们会发现是对引用计数m_uReference进行-1 *** 作,为0时删除对象

voID CCObject::release(voID){    CCAssert(m_uReference > 0,"reference count should greater than 0");    --m_uReference;    if (m_uReference == 0)    {        delete this;    }}


2.使用引用计数手动管理内存


因此,如果我们想手动来管理内存的释放,我们可以使用这样子,


        CCSprite* sprite1=new CCSprite();	sprite1->initWithfile("Closenormal.png");	cclOG("sprite1 retain:%d",sprite1->retainCount());//sprite1 retain:1	this->addChild(sprite1);         //addChild会对引用计数+1,可以跟踪看一下,最后会对object->retain() *** 作	cclOG("sprite1 retain:%d",sprite1->retainCount());//sprite1 retain:2	sprite1->release();	cclOG("sprite1 retain:%d",sprite1->retainCount());//sprite1 retain:1	this->removeChild(sprite1);    //对m_uReference进行-1,跟踪一下会发现对object进行CC_SAFE_RELEASE()安全释放 *** 作	cclOG("sprite1 retain:%d",sprite1->retainCount());//sprite1 retain:-17891602


new和release一般成对存在,所以,new和release是好基友!而手动内存管理一般不再使用retain。


3.自动管理autorelease


还记得helloWorld里面怎么创建一个Sprite吗?

CCSprite* pSprite = CCSprite::create("HelloWorld.png");


跟踪CCSprite::create()

CCSprite* CCSprite::create(const char *pszfilename){    CCSprite *pobSprite = new CCSprite();    if (pobSprite && pobSprite->initWithfile(pszfilename))    {        pobSprite->autorelease();        return pobSprite;    }    CC_SAFE_DELETE(pobSprite);    return NulL;}

上上面我们可以知道 : create=new+autorelease


那么autorelease是什么呢,我们接着跟踪进入autorelease方法:

CCObject* CCObject::autorelease(voID){    CCPoolManager::sharedPoolManager()->addobject(this);    return this;}
进入其中的addobject方法
voID CCPoolManager::addobject(CCObject* pObject){    getCurReleasePool()->addobject(pObject);}
再进入addobject方法
voID CCautoreleasePool::addobject(CCObject* pObject){    m_pManagedobjectArray->addobject(pObject);    CCAssert(pObject->m_uReference > 1,"reference count should be greater than 1");    ++(pObject->m_uautoReleaseCount);    pObject->release(); // no ref count,in this case autorelease pool added.}
然后我们可以发现俩个类:

CCPoolManager 对象自动管理类,这个类顾名思义就知道是对对象自动释放池进行管理的类,它是一个单例类,这里用来返回CCautoreleasePool

CCautoreleasePool 对象自动管理(释放)池。


从上面我们可以看到这样一句,将object添加到m_pManagedobjectArray 数组

m_pManagedobjectArray->addobject(pObject);

我们来看一下CCautoreleasePool 这个类

class CC_DLL CCautoreleasePool : public CCObject{    CCArray*    m_pManagedobjectArray;    public:    CCautoreleasePool(voID);    ~CCautoreleasePool(voID);    voID addobject(CCObject *pObject);    voID removeObject(CCObject *pObject);    voID clear();};

值得注意的是,这个类也是继承自CCObject,那么显然其内存管理形式也采用引用计数的。

这时看到类中的 m_pManagedobjectArray 数组,我们将对象autorelease后,都是将对象添加到这个数组中的,所以说是对象自动管理(释放)池。



再来回顾一下前面这个addobject方法

voID CCautoreleasePool::addobject(CCObject* pObject){    m_pManagedobjectArray->addobject(pObject);    CCAssert(pObject->m_uReference > 1,in this case autorelease pool added.}


首先是将对象添加到数组中,然后将对象自动管理变量++,那么对象的 m_uautoReleaseCount =1,也就是表明其为自动管理对象。


然后对对象进行release,也即对对象的引用计数进行减1的 *** 作,至于为什么要释放,这里解释下:


①首先一个CCSprite对象被创建,使用的是new,那么其引用计数 m_uReference=1。这个应该不难理解吧:CCSprite是继承自CCObject,而在前面CCObject的构造方法中就知道,new创建一个实例对象后,其引用计数m_uReference=1,而是否自动管理变量 m_uautoReleaseCount=0(表示对象未添加到自动管理(释放)池中自动管理)。


②接着对象autorelease,那么就是将对象添加到自动释放池中,而其中的:

m_pManagedobjectArray->addobject(pObject); 将被管理对象添加到自动管理池中的过程中(将对象添加到数组中),其会对对象进行retain *** 作的,所以 m_uReference 就变成了 m_uReference=2。

③所以最后的release是为了将引用计数重新变成为1。这样的话,从对象创建,到被放到对象自动管理池,引用计数依然为1,被管理值也为1(表征对象是自动管理)。


不信的话,下面我们来跟踪一下m_pManagedobjectArray->addobject(pObject)

voID CCArray::addobject(CCObject* object){    ccArrayAppendobjectWithResize(data,object);}
进入
/** Appends an object. Capacity of arr is increased if needed. */voID ccArrayAppendobjectWithResize(ccArray *arr,CCObject* object){	ccArrayEnsureExtraCapacity(arr,1);	ccArrayAppendobject(arr,object);}

在进入
/** Appends an object. Behavior undefined if array doesn't have enough capacity. */voID ccArrayAppendobject(ccArray *arr,CCObject* object){    CCAssert(object != NulL,"InvalID parameter!");    object->retain();	arr->arr[arr->num] = object;	arr->num++;}
看到object->retain()方法了吧。 总结

以上是内存溢出为你收集整理的cocos2d-x 内存管理机制全部内容,希望文章能够帮你解决cocos2d-x 内存管理机制所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1056904.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-25
下一篇 2022-05-25

发表评论

登录后才能评论

评论列表(0条)

保存