【玩转cocos2d-x之二十五】数据结构CCArray

来源:互联网 发布:飞鸽传书 公用网络 编辑:程序博客网 时间:2024/04/30 08:52

原创作品,转载请标明http://blog.csdn.net/jackystudio/article/details/16938787


CCArray是从cocos2d中移植过来的,类似于Apple的NSMutableArray,但是比NSMutableArray更为的好用。要注意的是虽然CCArray和CCDictionary可以管理cocos2d-x中绝大多数的类,但是仍然无法替代STL库,STL库更为强有力。


1.API

先看一下CCArray可以帮我们做什么。

1.1.创建

[cpp] view plaincopy
  1. //创建array  
  2. static CCArray* create();  
  3. //使用一系列CCObject创建array  
  4. static CCArray* create(CCObject* pObject, …);  
  5. //使用一个CCObject创建array  
  6. static CCArray* createWithObject(CCObject* pObject);  
  7. //创建array并设置容量  
  8. static CCArray* createWithCapacity(unsigned int capacity);  
  9. //用一个已存在的array创建另一个array  
  10. static CCArray* createWithArray(CCArray* otherArray);  

1.2.添加

[cpp] view plaincopy
  1. //添加一个元素  
  2. void addObject(CCObject* object);  
  3. //添加一个已存在array中所有元素  
  4. void addObjectsFromArray(CCArray* otherArray);  
  5. //在指定位置插入元素  
  6. void insertObject(CCObject* object, unsigned int index);  

1.3.删除

[cpp] view plaincopy
  1. //移除最后一个元素  
  2. void removeLastObject(bool bReleaseObj = true);  
  3. //移除某个元素  
  4. void removeObject(CCObject* object, bool bReleaseObj = true);  
  5. //移除一个指定位置的元素  
  6. void removeObjectAtIndex(unsigned int index, bool bReleaseObj = true);  
  7. //移除某个array  
  8. void removeObjectsInArray(CCArray* otherArray);  
  9. //移除所有元素  
  10. void removeAllObjects();  
  11. //快速移除某个元素  
  12. void fastRemoveObject(CCObject* object);  
  13. //快速移除某个指定位置的元素  
  14. void fastRemoveObjectAtIndex(unsigned int index);  


1.4.操作元素

[cpp] view plaincopy
  1. //返回元素个数  
  2. unsigned int count() const;  
  3. //返回array容量  
  4. unsigned int capacity() const;  
  5. //返回指定CCObject的位置,如果不存在返回UINT_MAX  
  6. unsigned int indexOfObject(CCObject* object) const;  
  7. //返回指定位置的CCObject  
  8. CCObject* objectAtIndex(unsigned int index);  
  9. //返回最后一个元素  
  10. CCObject* lastObject();  
  11. //返回随机元素  
  12. CCObject* randomObject();  
  13. //返回某个元素是否存在于array中  
  14. bool containsObject(CCObject* object) const;  
  15. //判断array是否相等  
  16. bool isEqualToArray(CCArray* pOtherArray);  

1.5.操作array内容

[cpp] view plaincopy
  1. //交换2个元素  
  2. void exchangeObject(CCObject* object1, CCObject* object2);  
  3. //交换2个指定位置元素  
  4. void exchangeObjectAtIndex(unsigned int index1, unsigned int index2);  
  5. //用一个对象替代指定位置元素  
  6. void replaceObjectAtIndex(unsigned int uIndex, CCObject* pObject, bool bReleaseObject = true);  
  7. //反转array  
  8. void reverseObjects();  
  9. //收缩array内存以匹配元素个数  
  10. void reduceMemoryFootprint();  


2.remove和fastremove

从1.3可以看出删除有两种方式,普通删除和快速删除,它们有什么区别呢?


2.1.普通删除

[cpp] view plaincopy
  1. //普通删除  
  2. void ccArrayRemoveObjectAtIndex(ccArray *arr, unsigned int index, bool bReleaseObj/* = true*/)  
  3. {  
  4.     CCAssert(arr && arr->num > 0 && index < arr->num, "Invalid index. Out of bounds");  
  5.     //删除元素内容,位置仍保留着  
  6.     if (bReleaseObj)  
  7.     {  
  8.         CC_SAFE_RELEASE(arr->arr[index]);  
  9.     }  
  10.     //长度减1  
  11.     arr->num--;  
  12.     //获得要删除的元素后的元素个数  
  13.     unsigned int remaining = arr->num - index;  
  14.     if(remaining>0)  
  15.     {  
  16.         //将要删除元素后的所有元素逐个向前移动  
  17.         memmove((void *)&arr->arr[index], (void *)&arr->arr[index+1], remaining * sizeof(CCObject*));  
  18.     }  
  19. }  

2.2.快速删除

[cpp] view plaincopy
  1. //快速删除  
  2. void ccArrayFastRemoveObjectAtIndex(ccArray *arr, unsigned int index)  
  3. {  
  4.     //删除元素内容,位置仍保留着  
  5.     CC_SAFE_RELEASE(arr->arr[index]);  
  6.     //获取最后一个元素  
  7.     unsigned int last = --arr->num;  
  8.     //把最后一个元素插到删除元素的位置上  
  9.     arr->arr[index] = arr->arr[last];  
  10. }  

2.3.总结

如果有array={0,1,2,3,4,5},如果要删除3,使用普通删除得到的结果{0,1,2,4,5},使用快速删除得到的结果是{0,1,2,5,4}。可以看出快速删除的效率比普通删除效率高,就差在移动元素的时间复杂度上。


3.内存分配


3.1.容量和个数

CCArray中容量和个数并不是同一个概念。个数<=容量。从添加元素的源码中可以看到在添加之前会先进行空间分配,所以它是一个动态分配内存的过程。如下

[cpp] view plaincopy
  1. void ccArrayEnsureExtraCapacity(ccArray *arr, unsigned int extra)//确保有额外的空间  
  2. {  
  3.     while (arr->max < arr->num + extra)//判断空间是否足够  
  4.     {  
  5.         ccArrayDoubleCapacity(arr);//增加一倍空间  
  6.     }  
  7. }  
所以,每次CCArray在插入数据时检测到空间不足会增加一倍空间,再进行检测,直到空间满足分配为止。


3.2.判等

判断2个CCArray是否相等使用isEqualToArray(),判断相等的条件是CCArray中的每个元素相等即可,与CCArray的容量无关。

4.效率

比起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数据结构和类型。


5.CCARRAY_FOREACH和CCARRAY_FOREACH_REVERSE

宏定义,用于正向遍历和反向遍历CCArray元素

[cpp] view plaincopy
  1. #define CCARRAY_FOREACH(__array__, __object__)                                                                         \  
  2.     if ((__array__) && (__array__)->data->num > 0)                                                                     \  
  3.     for(CCObject** __arr__ = (__array__)->data->arr, **__end__ = (__array__)->data->arr + (__array__)->data->num-1;    \  
  4.     __arr__ <= __end__ && (((__object__) = *__arr__) != NULL/* || true*/);                                             \  
  5.     __arr__++)  
  6.   
  7. #define CCARRAY_FOREACH_REVERSE(__array__, __object__)                                                                  \  
  8.     if ((__array__) && (__array__)->data->num > 0)                                                                      \  
  9.     for(CCObject** __arr__ = (__array__)->data->arr + (__array__)->data->num-1, **__end__ = (__array__)->data->arr;     \  
  10.     __arr__ >= __end__ && (((__object__) = *__arr__) != NULL/* || true*/);                                              \  
  11.     __arr__--)  


6.示例

CCArray的使用示例在http://blog.csdn.net/jackystudio/article/details/11917875此文中有比较典型的应用,这里就不再详述。


7.注意

一般来说,CCArray不会被add到其他类,所以它的引用计数是1,而且被设置为自动释放。所以创建CCArray对象时要记得调用retain,而且在析构的时候也要调用release来释放内存。真心想吐槽。。。