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,255);line-height:1.5 !important;">object);
}
* Appends an object. Behavior undefined if array doesn't have enough capacity. void ccArrayAppendObject(ccArray *arr,255);line-height:1.5 !important;">object
)
{
CCAssert(object != NULL,0);line-height:1.5 !important;">Invalid parameter!
");
object->retain();
此处果然retain了一下
arr->arr[arr->num] =
object;
arr->num++
;
}
接下来我们来看一下cocos2dx如何销毁那些无效的对象实例,以下是整个程序的主循环:
void
CCDisplayLinkDirector::mainLoop(
if (m_bPurgeDirecotorInNextLoop)
{
m_bPurgeDirecotorInNextLoop =
false;
purgeDirector();
}
else if (!
m_bInvalid)
{
drawScene();
release the objects
CCPoolManager::sharedPoolManager()->
pop();
}
}
由上面函数可知coco2dx在每一帧的帧尾会调用自动释放内存池的管理者—CCPoolManager的pop()函数,我们来看看该函数主要做了哪些工作?
void
CCPoolManager::pop()
{
if (!
m_pCurReleasePool)
{
return;
}
int nCount = m_pReleasePoolStack->
count();
m_pCurReleasePool->
clear();
if(nCount >
1)
{
m_pReleasePoolStack->removeObjectAtIndex(nCount-
1);
if(nCount > 1)
{
m_pCurReleasePool = m_pReleasePoolStack->objectAtIndex(nCount - 2);
return;
}
m_pCurReleasePool = (CCAutoreleasePool*)m_pReleasePoolStack->objectAtIndex(nCount -
2);
}
m_pCurReleasePool = NULL;*/
}
主要做的就两点:1、清除当前的自动释放池,2、更新当前自动释放池指针;我们来看看他是如何clear?
void
CCAutoreleasePool::clear()
{
if(m_pManagedObjectArray->count() >
0)
{
CCAutoreleasePool* pReleasePool;
#ifdef _DEBUG
int nIndex = m_pManagedObjectArray->count() -
1;
#endif
CCObject* pObj =
NULL;
CCARRAY_FOREACH_REVERSE(m_pManagedObjectArray,pObj)
{
if(!
pObj)
break;
--(pObj->
m_uAutoReleaseCount);
if( (
int)(pObj->m_uAutoReleaseCount)<
0 ){
pObj->m_uAutoReleaseCount =
0;
}
(*it)->release();
delete (*it);
#ifdef _DEBUG
nIndex--
;
#endif
}
m_pManagedObjectArray->
removeAllObjects();
}
}
以上函数主要做的工作是:1、将内部的所有元素的自动释放引用m_uAutoReleaseCount减一。2、清除内部的所有元素。看到这里我很诧异:为什么要清除所有的元素呢?难道不是清除那些无效的对象实例吗?紧接着看下面的函数看他如何removeAllObjects。
void
CCArray::removeAllObjects()
{
ccArrayRemoveAllObjects(data);
}
void ccArrayRemoveAllObjects(ccArray *
arr)
{
while( arr->num >
0 )
{
(arr->arr[—arr->num])->release();
注意此处的—arr->num
}
}
以上函数其实就是将数组内部的所有元素release一下,并将元素个数减为0。到这里整个对象创建—添加到自动释放池—帧尾的释放的过程就完了,我一开始很是纳闷,假如我有定义了一个类如下:
class A :
public CCNode
{
private:
CCSprite*
m_pSprite1;
CCSprite*
m_pSprite2;
public:
CREATE_FUNC(A);
bool init();
};
bool A::init()
{
m_pSprite1 = CCSprite::create(“
1.png”);
创建精灵1
m_pSprite2 = CCSprite::create(“
2.png”);
创建精灵2
this->addChild(m_pSprite);
只将精灵1添加到父节点
}
实际上到下一帧的时候,m_pSprite2所指向的内存已经无效,m_Sprite1仍然有效。上面的过程是如何做到的呢?只有这种情况才能解释:m_pSprite1和m_pSprite2在create的时候加入到了自动释放池被监视,而m_pSprite1再加入到父节点时retain了一下,才不会在帧尾release的时候被释放掉。我们来验证一下CCNode::addChild(…)(参数就不写了):
void
CCNode::addChild(CCNode *child,
int zOrder,255);line-height:1.5 !important;">int
tag)
{
CCAssert( child != NULL,0);line-height:1.5 !important;">Argument must be non-nil
");
CCAssert( child->m_pParent == NULL,0);line-height:1.5 !important;">child already added. It can't be added again
");
if( !
m_pChildren )
{
this->
childrenAlloc();
}
this->
insertChild(child,zOrder);
child->m_nTag =
tag;
child->setParent(
this);
child->setOrderOfArrival(s_globalOrderOfArrival++
);
if( m_bRunning )
{
child->
onEnter();
child->
onEnterTransitionDidFinish();
}
}
发现没有retain,继续看insertChild函数:
void CCNode::insertChild(CCNode* child,255);line-height:1.5 !important;">int
z)
{
m_bReorderChildDirty =
true;
ccArrayAppendObjectWithResize(m_pChildren->
data,child);
child->
_setZOrder(z);
}
发现也没有retain,继续看ccArrayAppendObjectWithResize函数
object);
}
任然没有retain,继续看ccArrayAppendObject函数
object->retain();
arr->arr[arr->num] = 终于发现了retain。
总结:当一个CCObject实例被创建:
1、若被autorelease(),那么在当前帧的帧尾会被release()一次(注意仅仅一次,以后就会被移除监视),若之前加入到了父节点中那么帧尾的release()时会避免释放,反之则会被无情的释放掉。如果没有加入到父节点又想想拥有该对象,那么需要自己retain();
2、若没有autorelease(),那么这个实例就需要自己来管理。
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!