坑爹的CCARRAY_FOREACH
第一次使用CCARRAY_FOREACH遍历一个CCArray数组并且删除数组里的东西时发生出乎意料的结果: CCArray*children=this->getChildren(); CCObject*temp=NULL;CCARRAY_FOREACH(children,temp) { CCSprite*sprite=dynamic_cast<CCSprite*>(temp); if(sprite->getTag()==1) { this->removeChild(sprite); } }
#defineCCARRAY_FOREACH(__array__,__object__) if((__array__)&&(__array__)->data->num>0) for(CCObject**__arr__=(__array__)->data->arr,**__end__=(__array__)->data->arr+(__array__)->data->num-1; __arr__<=__end__&&(((__object__)=*__arr__)!=NULL/*||true*/); __arr__++) 然后追踪到void CCNode::removeChild(CCNode* child)-> void CCNode::removeChild(CCNode* child,bool cleanup)-> void CCNode::detachChild(CCNode *child,bool doCleanup)-> 最后定位到detachChild中的m_pChildren->removeObject(child);是关键 m_pChildren是一个CCNode中的一个CCArray类型变量,CCArray中调用removeObjectsInArray又调用了ccArray类中的ccArrayRemoveArray函数, 最终定位到ccArrayRemoveObjectAtIndex中的memmove((void *)&arr->arr[index],(void *)&arr->arr[index+1],remaining * sizeof(CCObject*)); memmove函数中把CCArray中当前要删的那个项删掉,然后后面的项往前移动,所以当有两个连续的项Tag为1的精灵为A、B,并且当前的__arr__指向A精灵,当把当前__arr__指向的精灵(A精灵)删掉后,同时也执行了把后面B精灵往前移动了,所以本轮循环结束后,执行__arr__++后,__arr__指向的是B精灵后面的精灵的地址,所以B精灵成为了漏网之鱼。 结论:不要在CCARRAY_FOREACH遍历CCArray时删除里面存的对象。但是可以用CCARRAY_FOREACH_REVERSE宏,因为这个宏是从后面遍历的。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |