NSmutableArray 的实现原理机制
Posted 旅途
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NSmutableArray 的实现原理机制相关的知识,希望对你有一定的参考价值。
古老的C数组:
优点:查询速度很快,直接通过下表找到对应的值
缺点:修改、删除数据很慢,需要移动基于所有的其他的元素
插入和删除一个元素,需要移动后面所有的元素
改进的目标:实现快速增加,删除
NSMutableArray的内部数据结构如下:
几个主要变量:
offset: 有效数据起始位置偏移量
size: 实际占用的内存大小
used: 数组的实际的有效数据个数
*list: 实际内存的起始地址
删除元素
[arr removeObjecAtIndex:0];
[arr removeObjecAtIndex:0];
执行两次 remove的实现:
仅仅修改 offset即可,内存完全不需要移动。
那么问题来了,移走的这个元素的内存怎么释放的呢?
回到OBJC的引用计数,offset移走,这个对象的引用计数减一,对象引用计数到0之后,由autoreleasepool释放。over
插入元素
[arr insertObjec:@"test"atIndex:0];
执行insertObjec的实现:
如果buff的size还够用,不需要扩展buff,数据会在buff的末端添加进去,此时offset由0变成size-1,used+1.over
循环buff的牛逼之处就在于此,无需移动内存,实现插入元素。
删除元素
[arr removeObjecAtIndex:3];
实现:
删除头尾元素直接修改offset或者used即可
但是如果删除中间元素,就避免不了移动其他元素,不过NSArray会选择更少移动的那一边移动数据。
所以我们在实际使用过程中应该尽量避免这么做。
tip:
NSMutableArray *array = [NSMutableArray array];
for (int i = 0; i < 10000; i++) {
[array addObject:[NSObject new]];
}
[array removeAllObjects];
数组移除所有元素,buff并不会被立即清空
输出size的结果:
如果你在利用NSArray保存大量数据的时候,就要注意了。remove之后,记得置为nil,才能立刻释放掉buff.
总结:
1.数组越界奔溃: index > _used+offset 或 index < 0。
2.如果想要内存记录释放,remove之后记得置nil.或者直接置nil.猜想Array的dealloc的方法会自动给所有元素发release消息。
以上是关于NSmutableArray 的实现原理机制的主要内容,如果未能解决你的问题,请参考以下文章
按字典键的值对包含 NSMutableDictionary 的 NSMutableArray 进行排序