探索对象的底层原理-alloc(下)

149 阅读3分钟

今天继续探索alloc底层原理 WechatIMG61.png

一、影响对象内存的因素

我们先来创建一个类,在类中先创建成员变量,然后我们看打印出的结果 WechatIMG63.png WechatIMG62.png 接下来再在类中加一个实例方法和一个类方法,看对象所占的内存 WechatIMG64.jpeg WechatIMG65.jpeg WechatIMG68.png 通过以上发现实例方法和类方法对对象所占内存大小没有影响,只与isa和成员变量有关

二、对象的内存分布

用到的指令有p/po,

po:只会输出对应的值或者对象地址 + 类名,

p:输出值 + 值类型 + 引用名 + 内存地址 WechatIMG69.png x/6gx p:以16进制的形式打印p对象的6个8字节内存地址 WechatIMG70.png 打印处理的内存地址第一个是isa,为什么第三个才是p的name,而不是第一个呢? WechatIMG71.png 因为系统会自动重排属性变量的顺序会把4个字节的int和2字节的short放到一起,将不足8字节的放到一个里面(对象内部是以8字节对齐的),达到优化内存的目的

下面我们再看一个关于继承类的内存空间变化 WechatIMG73.png WechatIMG72.png 现将父类的成员变量顺序调整 WechatIMG74.png WechatIMG75.png 子类继承父类的数据结构的时候,父类是块连续的内存空间,子类是不能修改父类的数据结构,系统重排是不会将父类的成员变量和子类的成员变量重排在一起的,子类可以在不改变父类的数据结构的基础上往父类的后面添加子类的成员变量

成员变量的顺序是会对对象的内存空间产生影响的

三、联合体、位域

位域:位域的长度不能超过数据类型的最大长度 WechatIMG78.png WechatIMG77.png WechatIMG79.png 由此,位域能节省一定的内存空间

WechatIMG85.png 以上是结构体打印数据 WechatIMG88.png WechatIMG90.png 以上是联合体打印数据

系统分配一块足够大的内存空间,联合体里面的成员共用一块内存空间

联合体:1.必须能够容纳最大的成员变量, 2.通过1计算出来的大小,必须是其最大成员变量(基本类型)的整数倍

联合体与结构体的区别:联合体互斥(节省内存空间)、结构体共存(内存开辟比较粗放)

四、nonPointerIsa(内存优化的功能)

nonPointerIsa存储的内容,如下: WechatIMG246.png

五、如何利用isa的位运算得到类对象

1.通过位移的方式得到类对象 WechatIMG253.png 在amr64中,52是类对象,我们应右移3位 WechatIMG247.png WechatIMG248.png 左移12位 WechatIMG249.png 再右移9位就可以得到类对象 WechatIMG250.png 2.通过ISA_MASK WechatIMG255.png WechatIMG254.png

六、new方法

new = alloc + init

我们创建类,打印出来的内容一样 WechatIMG259.png WechatIMG260.png WechatIMG258.png 下面我们在源码看到的new返回的就是calloc WechatIMG256.png 汇编中通过objc_opt_new返回calloc WechatIMG257.png

我自己电脑运行的汇编在new处进入的是objc_msgSend,通过objc_msgSend调用alloc WechatIMG261.png