对象的本质、内存管理机制

OC题目自答

1、请讲讲对像的本质、内存管理机制。

答:

内存大小:

系统为NSObject对象分配了1

6个字节(通过malloc_size获得的),但是NSObject对象内部实际只使用了8个字节(通过class_getInstanceSize获得的),这是isa占用的大小。

内存对齐:

假设一个Person对象继承自NSObject,有一个int属性a,那么这个对象占16个字节。因为8+4 = 12,12<16 ,算作16个,如果还有一个int b,那么刚好是16了。 如果还有一个int c呢? 这时候就变成32了。因为 8 + 4 *3 = 20,原本只占了20个字节,但是需要遵循内存对齐原则,所以是16翻倍, 结果变成32了。

对象种类及isa指向:

OC对象分为3类:实例对象、类对象、元类对象。

实例对象的isa指向类对象、类对象的isa指向元类对象、元类对象的isa指向基元类对象

OC类信息存放的位置:

对象方法、属性、成员变量、协议信息、存放在类对象中。

类方法,存放在元类对象中

成员变量的具体值,存放在实例对象中。

为什么把对象的本质与内存管理机制放在一起?

因为实例对象的isa中存放了与内存管理紧密相关的东西:引用计数。

ARC中,OC对象在刚创建出来时,引用计数就位1,当被其他对象强引用时,引用计数会加1,失去强引用则减1,当引用计数为0的时候,对象则被销毁。

isa指针占用了8个字节,每个字节又有8个二进制位,那么一共就占用了64个二进制位。其中有19个二进制位用来存放引用计数,当这19个二进制位已经不够存下引用计数的时候,另一个二进制位存放的bool会变成yes,此时,系统会去另一个地方找引用计数:sideTable。

既然提到内存管理,也可以简单延伸聊几句开发中常遇到的内存泄漏问题,内存泄漏一般是由循环强引用导致的,比如A强引用了B,B又强引用了A,这样如果A想销毁的话,需要等B先销毁才行。B想销毁呢,又需要A先销毁。这样你等我先,我等你先,就谁都销毁不了,这样就出现了内存泄漏。

如何打破这种僵局呢?只需将其中一根线变成虚线,也就是弱引用。比如A强引用了B,但是B弱引用A,这样就不存在前面说的僵局了。

或者使用NSProxy,插入第三者,比如A强引用B,B强引用Proxy,Proxy弱引用A,形成一个三角形。其实原理都差不多,都是需要一根弱引用的线,来打破僵局。

还有就是,为什么,使用masonry布局时,在masonry的block内部使用self,不会出现内存泄漏?这个后面聊到block的时候,可以详细讲,包括为啥__weak 之后,就可以打破block循环循环也可以在后续详细讲。



在sideTable中 refcnts 其实就是引用计数。 weak_table 存放的是弱引用的计数。refcnts和weak_table都是散列表,使用对象的地址&上一个值,作为key,弱引用计数作为value。

OC中对象与swift中对象在内存中的区别:

OC:前8个字节放isa指针,接着后面放存储属性,比如age = 18、height = 175、、、

Swift:前8个字节放MetaData数据(类型信息),接着8个字节放引用计数(OC中的引用计数是通过isa指针去找的)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容