一、普通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. Python_爬虫_BeautifulSoup网页解析库

    BeautifulSoup网页解析库 from bs4 import BeautifulSoup 0.BeautifulSoup网页解析库包含 的 几个解析器 Python标准库[主要,系统自带;] ...

  2. 【SpringCloud】consul注册中心注册的服务为内网(局域网)IP

    一.前因 最近在做公司的一个微服务项目,技术架构为spring cloud + consul + SSM. 当我写完一个功能要在本地测试时,发现服务运行成功,但是前后端联调报500错误. 当时的第一个 ...

  3. phpstorm 远程调式 php

    https://cloud.tencent.com/developer/article/1561767 超时设置 fastcgi: ``` 1. apache module的情况下: 修改配置文件 h ...

  4. [代码审计]:PhpMyWind储存型XSS漏洞(CVE-2017-12984)

    简介 今天开启一下代码审计的篇章  python安全编程剩下的看起来没意思就结束了 ,现在规划每2周写一个爬虫练练手, 然后今天开启代码审计和Docker的学习 我个人感觉先看漏洞利用过程再看漏洞分析 ...

  5. 实验吧[WEB]——程序逻辑问题

    拿到题 通过查看网页源代码发现index.txt 通过index.txt我们获得了后端的源代码 我们可以通过我画出来的这两个重要的信息得知 第一个sql查询语句没有任何过滤说明存在SQL注入漏洞. 第 ...

  6. xdebug不显示

  7. java开发两年了,连个java代理模式都摸不透,你怎么跳槽涨薪?

    前言 代理模式(Proxy Pattern),23种java常用设计模式之一.代理模式的定义:代理类对被代理对象提供一种代理以控制对这个对象的访问.代理类主要负责为委托类预处理消息.过滤消息.把消息转 ...

  8. 如何在Vegas中安装激活Continuum插件

    视频剪辑插件Boris FX Continuum安装程序包含了多达250种插件.而视频剪辑软件Vegas Pro 18 Suite中提供了Boris FX Continuum Film Style U ...

  9. 【VUE】2.渲染组件&重定向路由

    1.删除多余组件,使环境赶紧 1. 整理App.vue, 删除多余内容,在template 模板区域增加一个路由占位符 router-view:渲染路径匹配到的视图组件 <template> ...

  10. docker和k8s的概念-IaaS、PaaS、SaaS 的区别

    docker和k8s 参考: 什么是Docker? Kubernetes概述 openstack,docker,mesos,k8s什么关系? IaaS.PaaS.SaaS的概念 SaaS:软件服务,S ...