ARC 原理

1.内存管理的思考原则

(1)自己生成的对象自己持有

(2)非自己生成的对象自己也能持有

(3)不再需要自己持有的对象时释放

(4)非自己持有的对象无法释放

2.Objective-C 方法 alloc/new/copy/mutableCopy  生成并持有对象

                                   retain方法                                  持有对象

                                   release方法                                释放对象

                                 dealloc方法                                   废弃对象

其中copy方法是基于NSCopying方法约定,由各类实现的copyWithZone方法:方法生成并持有对象的副本,与copy方法类似,mutableCopy方法是基于NSMutableCopying方法约定,由各类实现的mutableCopyWithZone:方法生成并持有对象的副本。两者的区别在于copy生成不可变更的对象,mutableCopy生成可变更的对象

3.autorelease方法功能:是对象在超出指定的生存范围时能够自动并正确的释放(释放时调用release方法)

autolease方法和release方法不同之处在于,release方法立即释放对象,autorelease方法把对象注册到autoreleasepool中,pool结束时自动调用release方法。

4.alloc/retain/release/dealloc 在GNUstep中的实现总结

(1)在Objective-C的对象中存有引用计数这一整数值(苹果实现此处不同)

(2)调用alloc或retain方法后,引用计数值加1

(3)调用release方法后,引用计数减1

(4)引用计数值为0时,调用dealloc方法废弃对象

5.苹果内存管理和引用计数的实现

(1)malloc 和 calloc区别

malloc只负责分配空间,对空间内的内容不做处理,需要memset函数对内存进行赋值

calloc函数分配空间后相应内存空间置0,

(2)GNUstep将引用计数对象保存在占用内存头部的变量中,而苹果的实现则是保存在应用计数表中

通过内存块头部管理引用计数好处如下:

少量代码即可完成

能够统一管理引用计数用内存块与对象用内存块

通过引用计数表管理应用计数好处如下:

对象用内存块分配无需考虑内存块头部

应用计数表各记录中存有内存块地址,可以从各个记录追溯到各对象的内存块

6.ARC所有权修饰符一共有四种(GNUstep实现)

__strong 修饰符

__weak 修饰符

__unsafe_unretained 修饰符

__autoreleasing 修饰符

__strong __weak 和 __autoreleasing 修饰符可以保证附有这些修饰符的自动变量初始化为nil

(1)__strong  修饰符

__strong 修饰符生成并持有对象,retainCount +1,id类型和对象类型的修饰符默认为__strong类型

(2)__weak 修饰符

主要用于解决循环引用问题

__weak 修饰符生成不持有对象,所以能够解决循环引用问题(循环引用容易发生内存泄漏。所谓内存泄漏就是应当废弃的对象超过其生命周期后继续存在)

循环引用:包括类成员变量的循环引用,自引用(对自身的强引用)

__weak修饰符在持有某一个对象的弱引用时。若该对象被废弃,则此弱引用自动失效且处于nil被赋值状态(空弱引用)。通过检查附有__weak修饰符的变量是否为nil,可以判断被赋值的对象是否被已被废弃

访问__weak修饰符的变量时,实际上必定要访问注册到autoreleasepool的对象。

原因:__weak修饰符之持有对象的弱引用,在访问弱引用的过程中,该对象有可能被废弃。如果把要访问的对象注册到autoreleasepool中,那么在@autoreleasepool块结束之前都能确保该对象的存在。因此,在使用附有__weak修饰符的变量时就必定要使用到autoreleasepool中的对象。

(3)__unsafe_unretained 修饰符

不安全的所有权修饰符。ARC式内存管理是编译器的工作,但是附有__unsafe_unretained 修饰符的变量不属于编译器的内存管理对象

__unsafe_unretained  修饰符和__weak修饰符的相同点

如id __unsafe_unretained obj = [[NSObject alloc] init];

上述代码将自己生成并持有的对象赋值给__unsafe_unretained修饰符修饰的变量中,所以obj不持有该对象,所以同__weak修饰符一样生成的对象会立即被释放(或者说随时有可能被释放)

异同点:

__unsafe_unretained 修饰符修饰的变量,超出其作用域释放后并不会置为nil,所以废弃后调用会导致程序崩溃(出现悬垂指针)

(4)__autoreleasing 修饰符

__autoreleasing 修饰符在ARC有效时并不显示调用,

使用@autoreleasepool{ 

}

你可能感兴趣的:(ARC 原理)