一、普通C语言的数组实现:

是开辟一段连续的内存空间,缺点:在插入下标为0的元素,会移动其他所有元素。添加,插入,删除同理。
 
 
 
 
 
当数组非常大时,这样很快会成为问题。
 
 

二、OC的NSMutableArray实现原理:

 
1、NSMutableArray 是一个类族,【【NSMutableArray new】 class】 打印出来的是 __NSArrayM。
2、通过class-dump逆向查看__NSArrayM里面的比较重要的成员变量:
      _used   : 计数
      _list      : 缓冲区指针
     _size     : 缓冲区大小
     _offset  : 缓冲区中的数组的第一个元素的索引
 
 
3、过程 原理,OC数组比C语言里的数组用了稍微复杂一点的环形缓冲区
环形缓冲区的特点是:在大多数情况下,除非缓冲区满了,否则不需要频繁分配内存。
并且NSMutableArray做到了如果我们在中间进行插入或者删除,只会移动最少的一边的元素。
来看一下 增、删、改、查。
查询:
以 -(void)objectAtIndex:(NSIteger)index; 为例子
 
答:-(void)objectAtIndex:(NSIteger)index
       {
         NSIteger originalOffset = _offset  + index;
         NSIteger reallOffset = originalOffset - ( _size > originalOffset ? 0 : size );
 
         Return  _list[ reallOffset ];
        }
分析:分两种情况,需比较 _size 与  _offset  + index的大小
A: 当 _size >=   _offset  + index 时:
 
B:当 _size <   _offset  + index 时:
 
 

三、证实过程:

增加:
由于逆向不出源码,我们用内存地址来证实这个原理
插入元素代码:
 
输出:
 
 
删除:
 
 
在没有插入55对象是的array打印结构:
 
 
插入 str5时,打印array对象:
 
 
 
 
补充:
x/100xb arr的意思是: 读取100个字节,并以16进制显示
  • 第一个x是memory read的简写(通过help x可以看出来)
  • 第二个x代表16进制
  • b代表字节
 
 
四、数组扩容
 
1、初始化给定容量时,系统会开辟对应的容量,在给定容量特别大时,会crash。
 
 
用new的方式初始化,没加入元素的时候,是还没有分配内存。
 
 
2、系统扩容:在现有容量 * 1.625, 0 - 2 - 2 * 1.625  -   2 * 1.625 * 1.625
 
 
 
3、扩容后删除元素,数组地址有缩容
A、删除所有元素
用removeLastObject,所有元素都删除,数组的内存地址还存在,容量为2
用removeAllObjects,所有元素都删除,数组被销毁
 
 
 
 
B、逐个删除元素
 
 
当有9个元素的时候:缩小规律是:10,4,2
当有100个元素的时候:缩小规律是:110,42,16,6,2
当有1205个元素的时候:缩小规律是:1600,640,256,98,38,14,6,2
 
总结:动态数组在删除元素的时候,会对用缩小容量。规则:d = 数组当前容量 / k ( k 为2.5 到 2.7中间的数,大家有兴趣可以自己逆向试试找一下这个数组); 当数组的元素数量 小于等于 d时,会在内存开辟一个大小为d的线性内存,把数组赋值到新地址中,达到节省内存的目的。
这块有个设计的注意点:扩容和缩容的比例不一样,可以避免临界值的性能问题。不会到达某个值添加一个扩容,删除一个缩小。
 
注:这块内容网上结识的比较少,是我自己总结,可以大家再一起讨论。
 
 
 

NSMutableArray 的实现原理的更多相关文章

  1. NSmutableArray 的实现原理机制

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

  2. Objective-C中block的底层原理

    先出2个考题: 1. 上面打印的是几,captureNum2 出去作用域后是否被销毁?为什么? 同样类型的题目: 问:打印的数字为多少? 有人会回答:mutArray是captureObject方法的 ...

  3. iOS-SDWebimage底层实现原理

    其实有些框架的实现原理,并没有想象中那么难,思想也很简单,主要是更新第三方框架的作者对自己写的代码,进行了多层封装,使代码的可读性降低,也就使得框架看起来比较难.我来实现以下SDWebimage的的曾 ...

  4. IOS热更新-JSPatch实现原理+Patch现场恢复

    关于HotfixPatch 在IOS开发领域,由于Apple严格的审核标准和低效率,IOS应用的发版速度极慢,稍微大型的app发版基本上都在一个月以上,所以代码热更新(HotfixPatch)对于IO ...

  5. JSPatch 实现原理详解

    原文地址https://github.com/bang590/JSPatch/wiki/JSPatch-%E5%AE%9E%E7%8E%B0%E5%8E%9F%E7%90%86%E8%AF%A6%E8 ...

  6. iOS开发——多线程篇——快速生成沙盒目录的路径,多图片下载的原理、SDWebImage框架的简单介绍

    一.快速生成沙盒目录的路径 沙盒目录的各个文件夹功能 - Documents - 需要保存由"应用程序本身"产生的文件或者数据,例如:游戏进度.涂鸦软件的绘图 - 目录中的文件会被 ...

  7. NSRunLoop 概述和原理

    NSRunLoop 概述和原理 1.什么是NSRunLoop? 我们会经常看到这样的代码: - (IBAction)start:(id)sender { pageStillLoading = YES; ...

  8. collectionView布局原理及瀑布流布局方式

    一直以来都想研究瀑布流的具体实现方法(起因是因为一则男女程序员应聘的笑话,做程序的朋友应该都知道).最近学习到了瀑布流的实现方法,瀑布流的实现方式有多种,这里应用collectionView来重写其U ...

  9. KVC/KVO原理详解及编程指南

    一.简介 1.KVC简介 2.KVO简介 二.KVC相关技术 1.Key和Key Path 2.点语法和KVC 3.一对多关系(To-Many)中的集合访问器方法 4.键值验证(Key-Value V ...

随机推荐

  1. 精尽 MyBatis 源码分析 - MyBatis 初始化(三)之 SQL 初始化(上)

    该系列文档是本人在学习 Mybatis 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释(Mybatis源码分析 GitHub 地址.Mybatis-Spring 源码分析 GitHub ...

  2. .Net orm 开源项目 FreeSql 2.0.0(满意的答卷)

    写在开头 2018年11月头脑发热到今天,一晃已经两年,当初从舒服区走向一个巨大的坑,回头一看后背一凉. 两年时间从无到有,经历数不清的日夜奋斗(有人问花了多长时间投入,答案:全职x2 + 两年无休息 ...

  3. 08vue绑定用户页面

    1.vue微博回调空页面 注:微博回调空页面为: http://127.0.0.1:8888/oauth/callback/ 1.1 页面路径 components\oauth.vue <tem ...

  4. Java基础教程——BigDecimal类

    BigDecimal类 float.double类型的数字在计算的时候,容易发生精度丢失. 使用java.math.BigDecimal类可以解决此类问题. 前面讲过Math类,现在的BigDecim ...

  5. docker安装myInfluxDB映射本地目录+开机后台自启动

    CentOS7环境 1.docker hup库搜索influxdb docker search influxdb 2.拉取influxdb镜像 docker pull influxdb 3.查看已下载 ...

  6. Beta冲刺随笔——Day_Nine

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 Beta 冲刺 这个作业的目标 团队进行Beta冲刺 作业正文 正文 其他参考文献 无 今日事今日毕 林涛: ...

  7. 冲刺随笔——Day_Seven

    这个作业属于哪个课程 软件工程 (福州大学至诚学院 - 计算机工程系) 这个作业要求在哪里 团队作业第五次--Alpha冲刺 这个作业的目标 团队进行Alpha冲刺 作业正文 正文 其他参考文献 无 ...

  8. ModelViewSet基础操作

    1 安装DjangoRestFramework pip install djangorestframework==3.11.1 2.在settings.py中注册 INSTALLED_APPS = [ ...

  9. SpringBoot系列:六、集成Swagger文档

    本篇开始介绍Api文档Swagger的集成 一.引入maven依赖 <dependency> <groupId>io.springfox</groupId> < ...

  10. Spring Boot 集成多个 Kafka

    一.配置文件 application.yml spring: kafka: one: bootstrap-servers: IP:PORT consumer: group-id: YOUR_GROUP ...