CCArray是从cocos2d中移植过来的,类似于Apple的NSMutableArray,但是比NSMutableArray更为的好用。要注意的是虽然CCArray和CCDictionary可以管理cocos2d-x中绝大多数的类,但是仍然无法替代STL库,STL库更为强有力。
API
先看一下CCArray可以帮我们做什么。
创建
创建1 2 3 4 5 6 7 8 9 10
| static CCArray* create();
static CCArray* create(CCObject* pObject, …);
static CCArray* createWithObject(CCObject* pObject);
static CCArray* createWithCapacity(unsigned int capacity);
static CCArray* createWithArray(CCArray* otherArray);
|
添加
添加1 2 3 4 5 6
| void addObject(CCObject* object);
void addObjectsFromArray(CCArray* otherArray);
void insertObject(CCObject* object, unsigned int index);
|
删除
删除1 2 3 4 5 6 7 8 9 10 11 12 13 14
| void removeLastObject(bool bReleaseObj = true);
void removeObject(CCObject* object, bool bReleaseObj = true);
void removeObjectAtIndex(unsigned int index, bool bReleaseObj = true);
void removeObjectsInArray(CCArray* otherArray);
void removeAllObjects();
void fastRemoveObject(CCObject* object);
void fastRemoveObjectAtIndex(unsigned int index);
|
操作元素
操作元素1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| unsigned int count() const;
unsigned int capacity() const;
unsigned int indexOfObject(CCObject* object) const;
CCObject* objectAtIndex(unsigned int index);
CCObject* lastObject();
CCObject* randomObject();
bool containsObject(CCObject* object) const;
bool isEqualToArray(CCArray* pOtherArray);
|
操作array内容
操作array内容1 2 3 4 5 6 7 8 9 10
| void exchangeObject(CCObject* object1, CCObject* object2);
void exchangeObjectAtIndex(unsigned int index1, unsigned int index2);
void replaceObjectAtIndex(unsigned int uIndex, CCObject* pObject, bool bReleaseObject = true);
void reverseObjects();
void reduceMemoryFootprint();
|
remove和fastremove
从API-删除可以看出删除有两种方式,普通删除和快速删除,它们有什么区别呢?
普通删除
普通删除1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void ccArrayRemoveObjectAtIndex(ccArray *arr, unsigned int index, bool bReleaseObj) { CCAssert(arr && arr->num > 0 && index < arr->num, "Invalid index. Out of bounds"); if (bReleaseObj) { CC_SAFE_RELEASE(arr->arr[index]); } arr->num--; unsigned int remaining = arr->num - index; if(remaining>0) { memmove((void *)&arr->arr[index], (void *)&arr->arr[index+1], remaining * sizeof(CCObject*)); } }
|
快速删除
快速删除1 2 3 4 5 6 7 8 9 10
| void ccArrayFastRemoveObjectAtIndex(ccArray *arr, unsigned int index) { CC_SAFE_RELEASE(arr->arr[index]); unsigned int last = --arr->num; arr->arr[index] = arr->arr[last]; }
|
总结
如果有array={0,1,2,3,4,5},如果要删除3,使用普通删除得到的结果{0,1,2,4,5},使用快速删除得到的结果是{0,1,2,5,4}。可以看出快速删除的效率比普通删除效率高,就差在移动元素的时间复杂度上。
内存分配
容量和个数
CCArray中容量和个数并不是同一个概念。个数<=容量。从添加元素的源码中可以看到在添加之前会先进行空间分配,所以它是一个动态分配内存的过程。如下
内存分配1 2 3 4 5 6 7
| void ccArrayEnsureExtraCapacity(ccArray *arr, unsigned int extra) { while (arr->max < arr->num + extra) { ccArrayDoubleCapacity(arr); } }
|
所以,每次CCArray在插入数据时检测到空间不足会增加一倍空间,再进行检测,直到空间满足分配为止。
判等
判断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_FOREACH和CCARRAY_FOREACH_REVERSE
宏定义,用于正向遍历和反向遍历CCArray元素
正反向遍历CCArray1 2 3 4 5 6 7 8 9 10 11
| #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); \ __arr__++) #define CCARRAY_FOREACH_REVERSE(__array__, __object__) \ if ((__array__) && (__array__)->data->num > 0) \ for(CCObject** __arr__ = (__array__)->data->arr + (__array__)->data->num-1, **__end__ = (__array__)->data->arr; \ __arr__ >= __end__ && (((__object__) = *__arr__) != NULL); \ __arr__--)
|
示例
CCArray的使用示例在此文中有比较典型的应用,这里就不再详述。
注意
一般来说,CCArray不会被add到其他类,所以它的引用计数是1,而且被设置为自动释放。所以创建CCArray对象时要记得调用retain,而且在析构的时候也要调用release来释放内存。真心想吐槽。。。