内存管理机制 - Animenzzzz/Study GitHub Wiki
内存中的对象主要有两类
-
一类是值类型,比如int、float、struct等基本数据类型。
-
一类是引用类型,也就是继承自NSObject类的所有的OC对象。前一种值类型不需要我们管理,后一种引用类型是需要我们管理内存的,一旦管理不好,就会产生非常糟糕的后果。
为什么值类型不需要管理,而引用类型需要管理呢?
1. 他们分配内存方式不一样。
- 值类型会被放入栈中,他们依次紧密排列,在内存中占有一块连续的内存空间,遵循先进后出的原则。
- 引用类型会被放到堆中,当给对象分配内存空间时,会随机的从内存当中开辟空间,对象与对象之间可能会留有不确定大小的空白空间,因此会产生很多内存碎片,需要我们管理。
2. 栈内存与堆内存从性能上比较:栈内存要优于堆内存,这是因为栈遵循先进后出的原则,但是当数据量过大时,存入栈会明显的降低性能。因此,我们会把大量的数据存入堆中,然后栈中存放堆的地址,当需要调用数据时,就可以快速的通过栈内的地址找到堆中的数据。
3. 值类型和引用类型之间是可以相互转化的
- 把值类型转化为引用类型的过程叫做装箱,比如把int包装为NSNumber,这个过程会增加程序的运行时间,降低性能。
- 把引用类型转为值类型的过程叫做拆箱,比如把NSNumer转为float,在拆箱的过程中,我们一定要注意数据原有的类型,如果类型错误,可能导致拆箱失败,因此会存在安全性的问题。
- 手动的拆箱和装箱,都会增加程序的运行时间,降低代码可读性,影响性能。
为什么要使用内存管理
因为Objc中所有的对象都是动态内存分配的,也就是都创建在堆控件中,整个过程由程序员来控制。其实objc对象的所有权,谁申请谁释放等都强调的是⼀件事,那就是责任制。整个对象的生命周期我们都要负责,所以我们需要⼀个稳定而合理的内存管理,出现了内存泄露的问题,因为程序员懒或疏忽了或是由程序结构造成的。
Objective-C管理内存的方式
1. 引用计数
这是一种古老但有效的内存管理方式。每个对象(特指:类的实例)内部都有一个retainCount的引用计数,对象刚被创建时,引用计数为1;可以手动调用retain方法使引用计数加1;同样也可以手动调用release方法使引用计数减1。
2. OC中提供了两种内存管理机制MRC和ARC来满足不同的需求。
- MRC手动管理内存(人工引用计数Mannul Reference Counting) MRC模式下,所有的对象都需要手动的添加retain、release代码来管理内存。使用MRC,需要遵守谁创建,谁回收的原则。也就是谁alloc,谁release;谁retain,谁release。 当引用计数为0的时候,必须回收,引用计数不为0,不能回收,如果引用计数为0,但是没有回收,会造成内存泄露。如果引用计数为0,继续释放,会造成野指针。为了避免出现野指针,我们在释放的时候,会先让指针=nil。
- ARC自动管理内存(自动引用计数Automatic Reference Counting)。 ARC是IOS5推出的新功能,通过ARC,可以自动的管理内存。在ARC模式下,只要没有强指针(强引用)指向对象,对象就会被释放。在ARC模式下,不允许使用retain、release、retainCount等方法。并且,如果使用dealloc方法时,不允许调用[super dealloc]方法。 ARC模式下的property变量修饰词为strong、weak,相当于MRC模式下的retain、assign。strong :代替retain,缺省关键词,代表强引用。weak:代替assign,声明了一个可以自动设置nil的弱引用,但是比assign多一个功能,指针指向的地址被释放之后,指针本身也会自动被释放。