【玩转cocos2d-x之二十】从CCObject看cocos2d-x的内存管理机制

【玩转cocos2d-x之二十】从CCObject看cocos2d-x的内存管理机制,第1张

概述原创作品,转载请标明:http://www.voidcn.com/article/p-yjmzlalc-ep.html 再看CCObject,剔除上节的拷贝相关,以及Lua脚本相关的属性和方法后,CCObject还剩下什么? 1.剩下什么? 可以看到整个CCObject就是围绕着m_uReference和m_uAutoReleaseCount在转。这两个变量的解释如下。所以CCObject剩下的其

原创作品,转载请标明:http://www.jb51.cc/article/p-yjmzlalc-ep.html


再看CCObject,剔除上节的拷贝相关,以及Lua脚本相关的属性和方法后,CCObject还剩下什么?


1.剩下什么?

可以看到整个CCObject就是围绕着m_uReference和m_uautoReleaseCount在转。这两个变量的解释如下。所以CCObject剩下的其实就是对内存的管理。

[cpp] view plain copy CCObject::CCObject(voID)//构造函数 :m_nLuaID(0) ,m_uReference(1)//引用计数,初始为1,当引用计数=0,自动释放该对象 ,m_uautoReleaseCount(0)//自动释放对象计数,如果是手动new的,则为0,如果autoRelease的,则在autoreleasePool会+1 //这里是保护成员,所以CCautoreleasePool被声明为友元类 { staticunsignedintuObjectCount=0;//静态成员,对象的计数,只增不减,用于标识唯一一个对象实例 m_uID=++uObjectCount; } CCObject::~CCObject(voID) if(m_uautoReleaseCount>0)//如果是自动管理,则在PoolManager中删除 CCPoolManager::sharedPoolManager()->removeObject(this); } //iftheobjectisreferencedbyLuaengine,removeit if(m_nLuaID) ccScriptEngineManager::sharedManager()->getScriptEngine()->removeScriptObjectByCCObject(else ccScriptEngineProtocol*pEngine=ccScriptEngineManager::sharedManager()->getScriptEngine(); if(pEngine!=NulL&&pEngine->getScriptType()==kScriptTypeJavaScript) { pEngine->removeScriptObjectByCCObject(this); voIDCCObject::release(//引用计数-1,如果引用计数=0,释放对象 CCAssert(m_uReference>0,"referencecountshouldgreaterthan0"); --m_uReference; if(m_uReference==0) deletethis; voIDCCObject::retain(//引用计数+1,防止被对象释放 CCAssert(m_uReference>0,"referencecountshouldgreaterthan0"); ++m_uReference; CCObject*CCObject::autorelease(//对象加入PoolManager,自动管理 CCPoolManager::sharedPoolManager()->addobject(return boolCCObject::isSingleReference(voID)const//返回是否唯一引用 returnm_uReference==1; unsignedintCCObject::retainCount(//返回引用计数 returnm_uReference; boolCCObject::isEqual(constCCObject*pObject)//判断对象是否相等 this==pObject; voIDCCObject::acceptVisitor(CcdataVisitor&visitor)//辅助对象执行动作 visitor.visitObject( }
2.内存管理

从CCObject可以看出,内存的管理方式有两种:手动管理和自动管理。


2.1.手动内存管理

想必从Java转到C++的朋友可能很受不了C++再申请完内存后还要手动释放,就像我从C++转Java时也同样很不习惯竟然不用管理内存,老是害怕会不小心让系统给销毁了。CCObject的成员变量m_uautoReleaseCount标识了是手动管理还是自动管理。如果执行以下 *** 作:

copy CCObject*obj=newCCObject();//m_uautoReleaseCount=0,m_uReference=1 从析构函数可以看到,析构函数是不对所有手动进行申请的变量进行内存释放(必须m_uautoReleaseCount>0)。那么这时得手动释放:

copy @H_830_419@ obj->release();//m_uReference-1后为0,执行deletethis; 所以,new和release是好基友!而手动内存管理一般不再使用retain。

2.2.自动内存管理

如果需要进行内存的自动管理,那要怎么做呢?

copy
obj->autorelease();//m_uautoReleaseCount=1,m_uReference=1

好了,什么都不用做,obj自生自灭了。

如果我们需要随时用到obj,而不愿意让它在我们不知情的情况下被释放,那么使用:

copy obj->retain(); 当不再需要它的时候,使用:

copy

又恢复回去了,所以,retain和release是好基友,一般在自动内存管理使用。


这里只是大概写一下如何使用new,autorelease,retain和release,至于内存管理的实现网上的代码解析很多,发现自己没办法深入浅出地写出来,所以还是放弃再写一回注释了,原理可以这么理解:Cocos2d-x提供了一个内存管理器类CCPoolManager,它包含了一个CCArray容器m_pReleasePoolStack,这个容器用来存放一些容器管理类CCautoreleasePool的实例对象。需要自动进行内存释放的CCObject实例对象会把其指针存放在容器管理类CCautoreleasePool的实例对象中的m_pManagedobjectArray容器里。所有存在其中的CCObject实例对象在进行释放 *** 作时通过使用计数器来进行判断在何时真正释放内存,游戏在每一帧结束时都会对autorelease对象进行释放。

2.3.一个疑问

平时我们可能会这么用:

copy //CTestLayer.h classCTestLayer:publiccocos2d::cclayer public: virtualboolinit(); CREATE_FUNC(CTestLayer); virtualvoIDupdate(floatdelta); private: CCSprite*background; }; //CTestLayer.cpp boolCTestLayer::init() if(!cclayer::init()) false; background=CCSprite::create("background.png"); this->addChild(background); this->scheduleUpdate(); true; floatdelta) background->setpositionY(background->getpositionY()-0.1); } background是create出来的,可以知道它是调用了autorelease,属于自动管理对象,而且我们又没有进行retain *** 作,按道理在执行update的时候background已经是要被销毁的,但是实际并没有。问题就出在这一句:

copy this->addChild(background);

至于为什么,大家翻一下addChild实现源码就知道啦~

总结

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

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

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

原文地址:https://www.54852.com/web/1065412.html

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

发表评论

登录后才能评论

评论列表(0条)

    保存