一、介绍
栈区
特点:由编译器自动完成分配和释放,不需要程序员手动管理,主要存储了函数的参数和局部变量值等。
堆区
特点:需要程序员手动开辟并管理内存。(OC有ARC, OC对象通常不需要程序员考虑释放问题)
BSS段 (全局区)(静态区)
特点:程序运行过程内存的数据一直存在,程序结束后由系统释放
常量区 (数据段)
特点:专门用于存放常量,程序结束后由系统释放
程序代码区
特点:用于存放程序运行时的代码,代码会被编译成二进制存进内存的程序代码区
总结:内存五大区
1、栈区和堆区是运行时分配的内存,其它区是编译时分配的
2、栈区的地址是连续的,并且是由高到低分配的
3、堆区的地址是不连续的,堆区的访问速度没有栈区块
二、引用计数是怎么存储的
1.如果对象使用了TaggedPointer, 苹果会直接将其指针值作为引用计数返回
- 引用计数可以直接存储在优化过的isa指针中
-
如果isa指针存储不下, 引用计数就会把一部分存储在一个散列表中
三、Tagged Pointer
1.Tagged Pointer专门用来存储小的对象,例如NSNumber和NSDate。
2.Tagged Pointer指针的值不再是地址了,而是真正的值。所以,实际上它不再是一个对象了,它只是一个披着对象皮的普通变量而已!所以,它的内存并不存储在堆中,也不需要malloc和free。
3.在内存读取速度快
引用计数
四、Weak实现原理概括:
- 弱应用对象, 底层也是使用了哈希存储,或者叫散列存储,那么是对象的内存地址作为key, 指向该对象的所有弱应用的指针作为值
-
释放时,就是以对象的内存地址作为key,去存储弱引用对象的哈希表里, 找到所有的弱引用对象,然后设置为nil , 最后移除这个弱引用的散列表..
weak,__unsafe_unretained, unowned 与 assign区别
1.__unsafe_unretained: 不会对对象进行retain,当对象销毁时,会依然指向之前的内存空间(野指针)
2.weak: 不会对对象进行retain,当对象销毁时,会自动指向nil
3.assign: 实质与__unsafe_unretained等同
4.unsafe_unretained也可以修饰代表简单数据类型的property,weak也不能修饰用来代表简单数据类型的property。
5.__unsafe_unretained 与 weak 比较,使用 weak 是有代价的,因为通过上面的原理可知,__weak需要检查对象是否已经消亡,而为了知道是否已经消亡,自然也需要一些信息去跟踪对象的使用情况。也正因此,__unsafe_unretained 比 __weak快,所以当明确知道对象的生命期时,选择__unsafe_unretained 会有一些性能提升,这种性能提升是很微小的。但当很清楚的情况下,__unsafe_unretained 也是安全的,自然能快一点是一点。而当情况不确定的时候,应该优先选用 __weak 。
6.unowned使用在Swift中,也会分 weak 和 unowned。unowned 的含义跟 __unsafe_unretained 差不多。假如很明确的知道对象的生命期,也可以选择 unowned。