-
cocos2d-x内存经管机制
添加时间:2013-6-28 点击量:cocos2d-x源于cocos2d-iphone,为了与Objective-c一致,cocos2d-x也采取了引用计数与主动收受接管的内存经管机制。
要实际主动内存收受接管,需持续于cocos2d-x的根类CCObject。当然主动开释会影响机能,解决规划看最后。
cocos2d-x中有很多静态工厂办法,例如以create开首的,这些静态工厂办法创建的对象都应用的autorelease,试想若是不消autorelease,
CCObject create(){CCObject ret = new CCObject(); return ret;}
此时函数内的引用在函数停止时就停止了,然则对方没有被开释,若是返回的ret没有被用户引用或者开释,那么就造成了内存泄漏。所以参加autorelease是个不错的解决办法。
看看CCObject的这两个字段和办法:
protected:
// 引用计数
unsigned int m_uReference;
// 主动开释次数 以前是bool m_bManaged;标识是否采取主动开释
unsigned int m_uAutoReleaseCount;
public:
void release(void);
void retain(void);
CCObject autorelease(void);
unsigned int retainCount(void);有这么一个原则:谁引用谁retain和release,对象传值时先retain再release(避免本身给本身传值时,先release可能会开释对象),调用release办法,当引用计数为0时,就会此对象。
内存经管autorelease是怎么实现的呢,进入autorelease看到调用了下面这个函数:
oolManager::sharedPoolManager()->addObject(this);将对象参加收受接管池
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.
}函数中将对象参加经管数组中,再对主动开释计数+1,然后release使引用计数-1。
当create一个对象时,new使引用计数为1,调用autorelease后,参加收受接管池,然后release引用计数-1。那么此时引用计数为0吗?
答案必然不是,若是为0,此时该对象就会被。cocos2d-x中的数据布局转为这种内存经管设置,如CCArray,当对array调用addObject时,就会调用retain使引用计数加1,当array调用removeObject时就会release。那么当参加收受接管池后,此时的这个引用归收受接管池所有,当一帧停止开释收受接管池的时辰,收受接管池中的所有对象都邑调用release。若是此时没有其他对象引用该对象,则该对象会被删除。
来看看主轮回mainLoop中的调用:
if (m_bPurgeDirecotorInNextLoop)
{
m_bPurgeDirecotorInNextLoop = false;
purgeDirector();
}
else if (! m_bInvalid)
{
drawScene();
// release the objects
oolManager::sharedPoolManager()->pop();
}每一帧停止调用sharedPoolManager()->pop()此时栈顶的收受接管池就被开释,此时池中的所有对象都邑被release,若是没有其它的对象(场景、层、数组等)在引用他们,就会被。而一帧开端又建树收受接管池sharedPoolManager()->push()。
可以看出每一帧收受接管池都要建树、删除,并且添加对象进入收受接管池,那么机能方面当然会受到影响,当收受接管池中对象很多时,发挥解析得很明显。
那么解决办法1:机能请求高的景象下不要随便马虎应用主动收受接管池。
办法2:手动开释并创建一个收受接管池
oolManager::shardPoolManager()->push();
for(int i=0; i!=n; ++i)
{
objArray[i]->autorelease();
}
oolManager::shardPoolManager()->pop();如许就不会让主动开释的对象集中在一帧停止的时辰。
读书,不要想着实用,更不要有功利心。读书只为了自身的修养。邂逅一本好书如同邂逅一位知己,邂逅一个完美之人。有时心生敬意,有时怦然心动。仿佛你心底埋藏多年的话,作者替你说了出来,你们在时光深处倾心相遇的一瞬间,情投意合,心旷神怡。