Object-C中的内存管理 MRC、ARC以及Autoreleasepool的区别

      自从iOS5之后,ARC的出现是的程序员不需要自己手动管理内存,大大的减少了工作负担以及出错的可能性。但感觉MRC的手动管理内存方式更容易让初学者理解iOS的内部运行机制,在此总结一下MRC、Autoreleasepool、ARC的区别


1.内存管理范围
内存中存在五大区域,他们分别是:堆区、栈区、数据段、BSS段以及代码段。其中,栈区用来存放局部变量,当声明局部变量的方法执行完毕之后局部变量才会被释放;BSS段以及数据段分别存放未初始化和已经初始化的全局变量、静态变量,数据段还会存放常量数据,程序结束的时候系统都会自动回收;代码段存放存储程序的代码,程序结束时也会自动回收;唯有堆区,堆区存放OC对象,需要程序员手动申请内存空间以及手动释放。所以,iOS中的内存管理实际上是管理内存中的堆区。
 

2.MRC模式
Object-C采用的是一种动态的内存管理方式,叫做引用计数,每一个OC对象都有一个引用计数器retainCount,对象被创建之后,引用计数器默认值为1。
引用计数器的数值代表对象被引用的次数,当多一个人引用这个对象的时候,retainCount + 1,当少一个人引用这个对象的时候,retainCount - 1,当retainCount 为0的时候系统会回收这个对象,调用该对象的dealloc方法。
MRC的本质就是通过代码来控制retainCount的值:为对象发送一条retain消息,retainCount + 1;为对象发送一条release消息,retainCount - 1,为对象发送一条retainCount消息,可以查看该对象当前的retainCount值。
#import 
#import "HITPerson.h"

int main(int argc, const char * argv[])
{   
    HITPerson *p1 = [[HMPerson alloc]init];  //此时p1的retainCount值为1
    [p1 retain];      //此时p1的retainCount值为2                
    [p1 release];     //此时p1的retainCount值为1
    [p1 release]; //此时p1的retainCount值为0,对象将被释放 
    return 0;
}
 
MRC内存管理的原则:
(1) alloc/new/retain 必须要和release配对使用
(2) 谁retain/alloc,谁就要负责release
(3)只有在增加一个人使用的时候,才为对象发送retain,只有在减少一个人使用的时候,才为对象发送release。
 
如果用户没有遵循内存管理的原则,就很容易造成内存泄漏或者出现野指针
内存泄漏:没有对不用的对象及时回收内存;
野指针:如果一个指针指向的对象已经被释放了,就把这个指针叫做野指针;

 
3.自动释放池Autoreleasepool
自动释放池是Object-C提供的一种对象自动进行释放的机制。它的基本思想是把需要进行释放的对象都放到一个空间存储起来,找个时机对这些对象一起发送release消息,相当于对对象的一个延时释放的过程。autoreleasepool就是负责储存需要release的对象的,等到autoreleasepool被销毁的时候(通常都是运行到大括号结束),对池内所有对象发送一遍release消息。
//创建自动释放池
@autoreleasepool
{

}   
在程序运行中,并不是把对象放到autoreleasepool里面就可以被自动释放,还需要调用该对象的autorelease方法才行,对象可以不在autoreleasepool里面创建,但是一定要在autoreleasepool里面调用autorelease方法,才能达到释放的目的。
HITStudent *stu = [[HITStuent alloc]init];
HITStudent *stu1 = [[HITStuent alloc]init];
HITStudent *stu2 = [[HITStuent alloc]init];
[stu2 retain];
@autoreleasepool
{
    HITStudent *stu3 =[[[HITStuent alloc] init] autorelease];
    [stu1 autorelease];
    [stu2 autorelease];
    [stu2 autorelease];  //stu2有一个retain操作,需要autorelease两次

}
上面代码中stu没有调用autorelease不能进行自动释放,stu1,stu2,stu3都能正常的进行自动释放。autorelease相当于一个延时的release,所以只要保证retain/alloc的总数与autorelease相等即可。
如果新建一个Single View Application工程,我们会发现在main()函数开始的时候就会生成一个自动释放池,,这样做并没有什么实际意义,因为就算不释放这些对象,程序结束后系统也会回收。真正使用autoreleasepool的场景是把大量使用临时变量的代码段或者需要长时间运行的代码段放到autoreleasepool中,从而提高内存使用率。


4.ARC模式
ARC叫做自动引用计数,是编译器的特性。ARC在编译期间会在程序的适当位置添加retain、release、autorelease等代码,从而无需程序员手动操作。并且在ARC模式下,不可以人为调用retain、release、autorelease、retainCount这些方法。

你可能感兴趣的:(iOS开发,Objective-C,重点)