目录(?)[-]
API 11创建 12添加 13删除 14 *** 作元素 15 *** 作array内容 remove和fastremove 21普通删除 2快速删除 3总结 内存分配 1容量和个数 2判等 效率 CCARRAY_FOREACH和CCARRAY_FOREACH_REVERSE 示例 注意
原创作品,转载请标明:http://www.jb51.cc/article/p-bsovodom-ep.html
CCArray是从cocos2d中移植过来的,类似于Apple的NSMutableArray,但是比NSMutableArray更为的好用。要注意的是虽然CCArray和CCDictionary可以管理cocos2d-x中绝大多数的类,但是仍然无法替代STL库,STL库更为强有力。
先看一下CCArray可以帮我们做什么。
1.1.创建[cpp] view plain copy //创建array staticCCArray*create(); //使用一系列CCObject创建array staticCCArray*create(CCObject*pObject,…); //使用一个CCObject创建array staticCCArray*createWithObject(CCObject*pObject); //创建array并设置容量 staticCCArray*createWithCapacity(unsignedintcapacity); //用一个已存在的array创建另一个array staticCCArray*createWithArray(CCArray*otherArray);
1.2.添加
copy @H_403_372@ //添加一个元素 voIDaddobject(CCObject*object); //添加一个已存在array中所有元素 voIDaddobjectsFromArray(CCArray*otherArray); //在指定位置插入元素 voIDinsertObject(CCObject*object,unsignedintindex);
1.3.删除
copy //移除最后一个元素 voIDremoveLastObject(boolbReleaSEObj=true); //移除某个元素 voIDremoveObject(CCObject*object,boolbReleaSEObj=true); //移除一个指定位置的元素 voIDremoveObjectAtIndex(unsignedintindex,108); List-style:decimal-leading-zero outsIDe; color:inherit; line-height:18px"> //移除某个array voIDremoveObjectsInArray(CCArray*otherArray); //移除所有元素 voIDremoveAllObjects(); //快速移除某个元素 voIDfastRemoveObject(CCObject*object); //快速移除某个指定位置的元素 voIDfastRemoveObjectAtIndex(unsignedintindex);
copy //返回元素个数 unsignedintcount()const; //返回array容量 unsignedintcapacity()const; //返回指定CCObject的位置,如果不存在返回UINT_MAX unsignedintindexOfObject(CCObject*object)const; //返回指定位置的CCObject CCObject*objectAtIndex(unsignedintindex); //返回最后一个元素 CCObject*lastObject(); //返回随机元素 CCObject*randomObject(); //返回某个元素是否存在于array中 boolcontainsObject(CCObject*object)const; //判断array是否相等 boolisEqualToArray(CCArray*pOtherArray);
1.5. *** 作array内容
copy //交换2个元素 voIDexchangeObject(CCObject*object1,CCObject*object2); //交换2个指定位置元素 voIDexchangeObjectAtIndex(unsignedintindex1,unsignedintindex2); //用一个对象替代指定位置元素 voIDreplaceObjectAtIndex(unsignedintuIndex,CCObject*pObject,boolbReleaSEObject=true); //反转array voIDreverSEObjects(); //收缩array内存以匹配元素个数 voIDreduceMemoryFootprint();
2.remove和fastremove
从1.3可以看出删除有两种方式,普通删除和快速删除,它们有什么区别呢?
copy //普通删除 voIDccArrayRemoveObjectAtIndex(ccArray*arr,unsignedintindex,boolbReleaSEObj/*=true*/) { CCAssert(arr&&arr->num>0&&index<arr->num,"Invalidindex.Outofbounds"); //删除元素内容,位置仍保留着 if(bReleaSEObj) CC_SAFE_RELEASE(arr->arr[index]); } //长度减1 arr->num--; //获得要删除的元素后的元素个数 unsignedintremaining=arr->num-index; if(remaining>0) //将要删除元素后的所有元素逐个向前移动 memmove((voID*)&arr->arr[index],(voID*)&arr->arr[index+1],remaining*sizeof(CCObject*)); } }
2.2.快速删除
copy //快速删除 voIDccArrayFastRemoveObjectAtIndex(ccArray*arr,unsignedintindex) //删除元素内容,位置仍保留着 CC_SAFE_RELEASE(arr->arr[index]); //获取最后一个元素 unsignedintlast=--arr->num; //把最后一个元素插到删除元素的位置上 arr->arr[index]=arr->arr[last]; }
2.3.总结
如果有array={0,1,2,3,4,5},如果要删除3,使用普通删除得到的结果{0,5},使用快速删除得到的结果是{0,5,4}。可以看出快速删除的效率比普通删除效率高,就差在移动元素的时间复杂度上。
CCArray中容量和个数并不是同一个概念。个数<=容量。从添加元素的源码中可以看到在添加之前会先进行空间分配,所以它是一个动态分配内存的过程。如下
copy voIDccArrayEnsureExtraCapacity(ccArray*arr,unsignedintextra)//确保有额外的空间 { while(arr->max<arr->num+extra)//判断空间是否足够 ccArrayDoubleCapacity(arr);//增加一倍空间 } 所以,每次CCArray在插入数据时检测到空间不足会增加一倍空间,再进行检测,直到空间满足分配为止。
3.2.判等
判断2个CCArray是否相等使用isEqualToArray(),判断相等的条件是CCArray中的每个元素相等即可,与CCArray的容量无关。
比起NSMutableArray,CCArray效率能高出10%左右,原因有三:
(1)它使用的是C接口,所以它不有Objective-C消息开销。
(2)它假定你知道你在做什么,所以它不花时间在安全检查上(如边界溢出,空间需求等)。
(3)在比较上使用了指针而不是isEqual。
除了CCArray,我们还看到了ccCArray,CCArray基本上都是调用了ccCArray的函数,为什么要分为2种?
仔细看一下CCArray是继承于CCObject,所以CCArray是用于处理cocos2d-x对象的,内存管理上也有cocos2d-x的autorelease等诸多特性。而ccCArray可以直接 *** 作标准的C数据结构和类型。
宏定义,用于正向遍历和反向遍历CCArray元素
copy @H_25_1301@#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__++) @H_25_1301@#defineCCARRAY_FOREACH_REVERSE(__array__,108); List-style:decimal-leading-zero outsIDe; color:inherit; line-height:18px"> for(CCObject**__arr__=(__array__)->data->arr+(__array__)->data->num-1,**__end__=(__array__)->data->arr;\ __arr__>=__end__&&(((__object__)=*__arr__)!=NulL/*||true*/);\ __arr__--)
CCArray的使用示例在http://www.jb51.cc/article/p-wfbmoohn-ep.html此文中有比较典型的应用,这里就不再详述。
一般来说,CCArray不会被add到其他类,所以它的引用计数是1,而且被设置为自动释放。所以创建CCArray对象时要记得调用retain,而且在析构的时候也要调用release来释放内存。真心想吐槽。。。
============
http://blog.csdn.net/kenkao/article/details/10375683
一.基本用法
1.声明初始化变量
@H_400_1419@ C++1 2 3 | cocos2d :: CCArray * pArray ; pArray = CCArray :: createWithCapacity ( 100 ) ; pArray -> retain ( ) ; //如果保留成员变量的话,因为标记了autorelease |
2.添加元素到数组
@H_400_1419@ C++1 2 | @H_301_1545@ CCSprite * pRet = CCSprite :: create ( "test.png" ) ; pArray -> addobject ( pRet ) ; //将pRet添加到数组0位置,此处会调用一次pRet的retain |
3.删除元素
@H_400_1419@ C++1 2 3 | //下面这两个函数都能够实现删除元素的效果 pArray -> removeObject ( pRet ) ; //第二参数为是否调用release,默认为true pArray -> removeObjectAtIndex ( 0 ) ; //删除o位置上的元素 |
4.遍历
1).使用ccarray中的宏进行遍历
@H_400_1419@ C++1 2 3 4 5 6 7 8 9 10 11 12 13 | CCObject * pObj ; //正向 CCARRAY_FOREACH ( s_pBulletArray , pObj ) { CMapNode * pNode = ( CMapNode * ) pObj ; //... } //逆向 CCARRAY_FOREACH_REVERSE ( s_pBulletArray , pObj ) { CMapNode * pNode = ( CMapNode * ) pObj ; //... } |
2).for循环遍历
@H_400_1419@ C++1 2 3 4 | for ( unsigned int i = 0 ; i < s_pBulletArray -> count ( ) ; ++ i ) { @H_301_1981@ CCNode * pObj = ( CCNode * ) s_pBulletArray -> objectAtIndex ( i ) ; } |
1.创建一个CCArray后如果不是立刻使用的话一定要调用retain,增加引用计数,不然会被自动释放!
2.删除CCArray中的元素时最好默认内部调用一次release,不然可能会内存泄露!
3.遍历时删除元素
@H_400_1419@ C++1 2 3 4 5 6 7 8 9 10 11 | //判断条件删除时,这样不会漏掉任何元素 for ( int i = arr -> count ( ) - 1 ; i >= 0 ; -- i ) { CMonster * pObj = ( CMonster * ) arr -> objectAtIndex ( i ) ; bool isCollIDe = false ; isCollIDe = rect . intersectsRect ( pObj -> getCollIDeRect ( ) ) ; if ( isCollIDe ) { arr -> removeObject ( pObj ) ; } } |
1.每一个CCNode的children本质就是一个CCArray,这样我们就可以通过getChildren()获得array,进行 *** 作!
2.对于CCSequence如果只有到运行时才能知道有个少个动作时,我们就可以声明一个CCArray然后将动作addobject(),最后通过一个array来创建CCSequence,例如下面这段代码:
@H_400_1419@ C++1 2 3 4 5 6 7 8 9 10 11 12 | //所有的路径节点 CCArray * array = CCArray :: createWithCapacity ( 20 ) ; float dt = 1 / ( m_pProperty -> fMoveSpeed ) ; CCPoint point ( - 1 , - 1 ) ; for ( UINT i = 0 ; i < CGlobal :: getGameMap ( ) -> m_PathNode . size ( ) - 1 ; ++ i ) { array -> addobject ( CCMoveto :: create ( dt , point ) ) ; } //移动完毕的回调 array -> addobject ( CCCallFunc :: create ( this , callfunc_selector ( CMonster :: onArrive ) ) ) ; CCSequence * pAct = CCSequence :: create ( array ) ; |
3.对于一个CCSprite,我们肯定需要把它addChild到parent上,这样他才能显示出来,这样的话parent上就会有好多child,但是我们要遍历只是其中的一部分(例:场景的地图上有好多种花,我们都会把它们添加到同一个parent上,这时候策划说其中的一种花会被怪物踩死?纳尼….,这个时候我们就需要唉将能被踩死的花加入到parent上时同时加入到一个CCArray中去….),这样我们用的时候遍历这个数组就可以了,而不是遍历这个children!
4.多谢@子龙山人 大大的添加,CCArray还可以内存预分配,比如预先生成一堆子d,然后加到CCArray中,再从这个CCArray中去重用子d。这样可以提高游戏效率。消失的子d只需要设置为Invisible就可以了。这个在做射击类游戏中会大量使用的!
5.还有其他用法?发评论告诉我!
总结以上是内存溢出为你收集整理的转【玩转cocos2d-x之二十五】数据结构CCArray全部内容,希望文章能够帮你解决转【玩转cocos2d-x之二十五】数据结构CCArray所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)