本来想分析CCArray的,结果发现实现部分基本都在ccArray里面,CCArray几乎只是将ccArray封装成了类,所以索性就直接分析ccArray了。
//- ccArray 实现里包含了retain和release操作 //- ccCArray 没有包含retain和release操作 typedef struct _ccArray { unsigned int num, max; CCObject** arr; } ccArray; // 分配指定大小的空间 ccArray* ccArrayNew(unsigned int capacity); // 释放空间 void ccArrayFree(ccArray*& arr); // 分配空间翻倍 一般不需要调用 只需调用ccArrayEnsureExtraCapacity即可 // 每次分配2倍空间的好处是:一次性分配空间 下次插入时 可更快的插入 免去空间分配的时间 思想有点像线程池 void ccArrayDoubleCapacity(ccArray *arr); // 确保空间足够 如果不够 翻倍 void ccArrayEnsureExtraCapacity(ccArray *arr, unsigned int extra); // 收缩 使空间与实际item数相同 void ccArrayShrink(ccArray *arr); // 获取指定元素的索引 unsigned int ccArrayGetIndexOfObject(ccArray *arr, CCObject* object); // 检查元素是否在array内 bool ccArrayContainsObject(ccArray *arr, CCObject* object); // 在末尾添加元素 不检查空间是否足够 所以在空间不足时 会出现无法预测的行为 void ccArrayAppendObject(ccArray *arr, CCObject* object); // 在末尾添加元素 空间不足时重新分配 void ccArrayAppendObjectWithResize(ccArray *arr, CCObject* object); // 在末尾添加一组元素 不检查空间是否足够 所以在空间不足时 会出现无法预测的行为 void ccArrayAppendArray(ccArray *arr, ccArray *plusArr); // 在末尾添加一组元素 空间不足时重新分配 void ccArrayAppendArrayWithResize(ccArray *arr, ccArray *plusArr); // 在指定位置插入元素 所有元素向后移动 void ccArrayInsertObjectAtIndex(ccArray *arr, CCObject* object, unsigned int index); // 交换位置 void ccArraySwapObjectsAtIndexes(ccArray *arr, unsigned int index1, unsigned int index2); // 移除所有元素 只移除 不收缩 void ccArrayRemoveAllObjects(ccArray *arr); // 移除指定元素 所有元素向前移动补空 不检查空间是否足够 所以在空间不足时 会出现无法预测的行为 void ccArrayRemoveObjectAtIndex(ccArray *arr, unsigned int index, bool bReleaseObj = true); // 移除指定元素 用最后一个元素补空 不检查空间是否足够 所以在空间不足时 会出现无法预测的行为 void ccArrayFastRemoveObjectAtIndex(ccArray *arr, unsigned int index); void ccArrayFastRemoveObject(ccArray *arr, CCObject* object); // 查找到指定的元素 并移除 只移除第一个匹配的 void ccArrayRemoveObject(ccArray *arr, CCObject* object, bool bReleaseObj = true); // 移除指定元素组 只移除第一个匹配的 void ccArrayRemoveArray(ccArray *arr, ccArray *minusArr); // 移除指定元素组 所有相同的都会被移除 void ccArrayFullRemoveArray(ccArray *arr, ccArray *minusArr);
挑了一部分简单分析。
void ccArrayEnsureExtraCapacity(ccArray *arr, unsigned int extra) { // 空间不足 直接翻倍 while (arr->max < arr->num + extra) { ccArrayDoubleCapacity(arr); } } void ccArrayShrink(ccArray *arr) { unsigned int newSize = 0; // 仅在需要重新分配时 重新分配空间 if (arr->max > arr->num && !(arr->num==0 && arr->max==1)) { if (arr->num!=0) { newSize=arr->num; arr->max=arr->num; } else {//保持空间最小为1 newSize=1; arr->max=1; } arr->arr = (CCObject**)realloc(arr->arr,newSize * sizeof(CCObject*) ); CCAssert(arr->arr!=NULL,"could not reallocate the memory"); } } void ccArrayAppendObject(ccArray *arr, CCObject* object) { CCAssert(object != NULL, "Invalid parameter!"); // 直接操作 不检查空间是否足够 object->retain(); arr->arr[arr->num] = object; arr->num++; } void ccArrayAppendObjectWithResize(ccArray *arr, CCObject* object) { // 先确保空间足够 再操作 ccArrayEnsureExtraCapacity(arr, 1); ccArrayAppendObject(arr, object); } void ccArrayInsertObjectAtIndex(ccArray *arr, CCObject* object, unsigned int index) { CCAssert(index<=arr->num, "Invalid index. Out of bounds"); CCAssert(object != NULL, "Invalid parameter!"); // 保证充足空间 ccArrayEnsureExtraCapacity(arr, 1); // 向后移位 让出足够空间 unsigned int remaining = arr->num - index; if( remaining > 0) { memmove((void *)&arr->arr[index+1], (void *)&arr->arr[index], sizeof(CCObject*) * remaining ); } // 插入 object->retain(); arr->arr[index] = object; arr->num++; } void ccArrayRemoveAllObjects(ccArray *arr) { while( arr->num > 0 ) {// 简单明了的release 附带--arr->num (arr->arr[--arr->num])->release(); } } void ccArrayFastRemoveObjectAtIndex(ccArray *arr, unsigned int index) { CC_SAFE_RELEASE(arr->arr[index]); // 用最后一个元素填补空缺 unsigned int last = --arr->num; arr->arr[index] = arr->arr[last]; }
CCArray内部使用了ccArray,也就是自带了retain及release操作的array。
顺带一提,有个ccCArray,是使用C方式的malloc和free操作的,这个只在引擎内部使用,我们自己一般是不会使用到这个的。
有趣的部分是分配空间时的操作,每次直接翻倍分配,一定程度上提高了效率。