坑爹的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);
    }
}

这段代码执行下来,发现有些Tag为1的精灵没有被删除,为了查原因,我追查到CCARRAY_FOREACH宏的定义中:

#define CCARRAY_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__++)

如果在我原来的代码中展开CCARRAY_FOREACH宏的话,代码为如下形式:

if ((children && children->data->num > 0)
    for(CCObject** __arr__ = children->data->arr, **__end__= children->data->arr + children->data->num-a;
         __arr__ <= __end__ && (((temp) = *__arr__) != NULL);
         __arr__++)
{
    CCSprite *sprite = dynamic_cast<CCSprite*>(temp);
    if(sprite->getTag() == 1)
    {
        this->removeChild(sprite);
    }
}

然后追踪到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宏,因为这个宏是从后面遍历的。

时间: 2024-10-10 14:07:04

坑爹的CCARRAY_FOREACH的相关文章

app里使用163邮箱发送邮件,被163认为是垃圾邮件的坑爹经历!_ !

最近有个项目,要发邮件给用户设定的邮箱报警,然后就用了163邮箱,代码是网上借来的^^,如下: package com.smartdoorbell.util; import android.os.AsyncTask; import java.util.Date; import java.util.List; import java.util.Properties; import javax.activation.CommandMap; import javax.activation.Mailca

小米电视支付SDK接入air坑爹之路

1. air的包名在生成android后会加入一个air的前缀变为air.***.***.mibox.包名与appid和appkey必须相相应才行,不然会一直返回40000错误 2. 加入了NativeApplication.nativeApplication.exit(),失去焦点退出,导致登录界面一直弹不出来 这俩坑爹问题! .!!

【TK】1023: 坑爹的黑店

1023: 坑爹的黑店 时间限制: 1 Sec  内存限制: 32 MB提交: 2134  解决: 855[提交][状态][下载(1元)] 题目描述 今天小明去了一个风景如画的地方散心,但是自己带的饮料喝完了,小明口渴难耐,见不远处有家小商店,于是跑去买饮料. 小明:"我要买饮料!" 店主:"我们这里有三种饮料,矿泉水1.5元一瓶,可乐2元一瓶,橙汁3.5元一瓶." 小明:"好的,给我一瓶矿泉水." 说完他掏出一张N元的大钞递给店主. 店主:&q

SQL Server--疑难杂症之坑爹的Windows故障转移群集

--============================================================== 估计是春节前最后一次写博客,也估计是本年值班最后一次踩雷,感叹下成也SQL SERVER,败也SQL SERVER. --============================================================== 场景描述: 操作系统版本 :Windows Server 2012 数据中心版本 数据库版本 :SQL SERVER 20

哦这。。!C语言scanf输入的坑爹之处

一. 今天闲来无事,跑去A题,本想3sA了poj1004,结果搞了10分钟,最令人困惑的问题就是为什么定义了double类型的变量,但是用scanf输入的时候标识符用%f的话,输入并不能完成,也就是说输入不会起作用,后来查找资料,才知道,原来用double 输入的时候标识符是%lf,注意这里是L和F,不是1和f 经过修正终于搞定,分分钟A了这个水题. 然而后来再想 A 就A不过去了,,,,并不知道为什么.好吧,忽略这种细节,没什么难度的水题没必要太在意,代码如下: 1 #include<cstd

&#31227;&#21160;&#31471;&#19978;&#19979;&#28369;&#21160;&#20107;&#20214;&#20043;--&#22353;&#29241;&#30340;touch.js

转:http://blog.csdn.net/minidrupal/article/details/39611605?utm_source=tuicool&utm_medium=referral 移动端页面的盛行,微信的便利的页面推广等等,让越来越多的css3效果和html5在手机端大放异彩。 于是乎,各式各样的简约酷炫的html5页面层出不穷,最多的就是视差滚动+css3动画。 接下来就说说自己在搞这些页面里面碰到的一个小问题-------zepto.js里面,坑爹的touch.js的上下滑动

移动端上下滑动事件之--坑爹的touch.js

原文   http://blog.csdn.net/minidrupal/article/details/39611605 移动端页面的盛行,微信的便利的页面推广等等,让越来越多的css3效果和html5在手机端大放异彩. 于是乎,各式各样的简约酷炫的html5页面层出不穷,最多的就是视差滚动+css3动画. 接下来就说说自己在搞这些页面里面碰到的一个小问题-------zepto.js里面,坑爹的touch.js的上下滑动( swipe )事件失效. 在举例之前,先科普一下如何在pc端,查看h

关于那些常见的坑爹的小bug(会持续更新)

当我学了矩阵分析的时候我知道什么是麻烦,当我学了傅里叶级数的时候我知道什么是相当麻烦.然而,当我刚刚接触前端,我才明白什么叫做坑爹的ie6.这个分享对于经验丰富的前端基本都遇过.对于刚入行的新手,或许可以起到一点点的指导作用.不求救万人于水火,但求某日能帮到路过的你. 在说bug之前,先看看各大浏览器最近的份额 有这个百度的浏览器份额可以看出ie6的末日渐行渐近了. 但是中国盗版的xp系统用户还不在少数,所以ie6在短期内不会消失.下面就说一下以ie6为首的一些奇葩而又常见的bug. 1.IE6

poj 1502 最短路+坑爹题意

链接:http://poj.org/problem?id=1502 MPI Maelstrom Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5249   Accepted: 3237 Description BIT has recently taken delivery of their new supercomputer, a 32 processor Apollo Odyssey distributed share