zoukankan      html  css  js  c++  java
  • NSmutableArray 的实现原理机制

    古老的C数组:

    优点:查询速度很快,直接通过下表找到对应的值
    缺点:修改、删除数据很慢,需要移动基于所有的其他的元素
     
    P160
    P155
    插入和删除一个元素,需要移动后面所有的元素
    改进的目标:实现快速增加,删除

    NSMutableArray的内部数据结构如下:

    P158


    几个主要变量:
    offset: 有效数据起始位置偏移量
    size: 实际占用的内存大小
    used: 数组的实际的有效数据个数
    *list: 实际内存的起始地址
    P156
     

    删除元素

    [arr removeObjecAtIndex:0];
    [arr removeObjecAtIndex:0];
    执行两次 remove的实现:
    P159

    仅仅修改 offset即可,内存完全不需要移动。
    那么问题来了,移走的这个元素的内存怎么释放的呢?
    回到OBJC的引用计数,offset移走,这个对象的引用计数减一,对象引用计数到0之后,由autoreleasepool释放。over

    插入元素

    [arr insertObjec:@"test"atIndex:0];

    执行insertObjec的实现:
     
    P154
     
    如果buff的size还够用,不需要扩展buff,数据会在buff的末端添加进去,此时offset由0变成size-1,used+1.over
    循环buff的牛逼之处就在于此,无需移动内存,实现插入元素。

    删除元素

    [arr removeObjecAtIndex:3];

    实现:
     
    P157
     
    删除头尾元素直接修改offset或者used即可
    但是如果删除中间元素,就避免不了移动其他元素,不过NSArray会选择更少移动的那一边移动数据。
    所以我们在实际使用过程中应该尽量避免这么做。

    tip:

    NSMutableArray *array = [NSMutableArray array];
     
    for (int i = 0; i < 10000; i++) {
        [array addObject:[NSObject new]];
    }
    [array removeAllObjects];
     
    数组移除所有元素,buff并不会被立即清空
    输出size的结果:
    1
    Size: 14336 
    如果你在利用NSArray保存大量数据的时候,就要注意了。remove之后,记得置为nil,才能立刻释放掉buff.
    总结:
    1.数组越界奔溃: index > _used+offset 或 index < 0。
    2.如果想要内存记录释放,remove之后记得置nil.或者直接置nil.猜想Array的dealloc的方法会自动给所有元素发release消息。

     
  • 相关阅读:
    RunLoop详解
    NSURLConnection基本用法(苹果原生)
    NSThread 基本使用
    NSOperation/NSOperationQueue详细使用介绍
    JSON解析
    XML解析
    GCD详细用法
    [Java]手动编译Java
    [Selenium] Grid 介绍
    [SoapUI] 循环遍历某个Test Case下的所有Test Step,将Cookie传递给这些Test Step
  • 原文地址:https://www.cnblogs.com/firstrate/p/8313443.html
Copyright © 2011-2022 走看看