栈:局部变量,当局部变量的作用域执行完之后,这个局部变量会立即被系统回收。
堆:存放OC对象、使用C函数申请的动态空间。
BSS段:存放未初始化的全局变量、静态变量,一旦初始化就回收,并存储到数据段中。
数据段:存放已初始化的全局变量、静态变量,直到程序介绍时才会被回收。
代码段:代码,程序结束时系统会自动回收存储在代码段中的数据。
栈、BSS段、数据段、代码段是由系统自动完成的。不需要人工干预。
存储在堆中的对象系统不会自动回收,那么肯定需要人工回收的,总不能系统结束了才回收吧?那么怎么回收呢?
对象什么时候回收?
当有人使用这个对象的时候,这个时候千万不能回收。只有在没有任何人使用这个对象的时候,才可以回收。
这时候引入一个概念:
每一个对象都有一个属性叫引用计数器(retainCount)
类型是unsigned long 占据八个字节。引用计数器(retainCount)
的作用,用来计入当前有多少个人在使用。创建一个对象出来的时候,默认情况下引用计数器(retainCount)
的默认值是1。当多一个使用这个对象的时候,就应该先让引用计数器的值加1,代表这个对象多一个人使用。当这个对象少一个对象的时候,应该先让这个对象的引用计数器的值减一,代表少一个人使用。当引用计数器的值为0的时候,代表无人使用这个对象,这时候系统的就会回收这个对象。
那么如何操作这个引用计数器呢?
1)、为对象发送一条retain消息,对象的引用计数器就会+1,当多一个人使用的时候才发。
2)、为对象发送一条release消息,对象的应用计数器就会-1,当少一个人使用对象的时候才发。
3)、为对象发送一条retainCount消息,就可以取到对象的引用计数器的值。
在对象被回收的时候,会自动调用dealloc方法。
MRC:Manual Reference Counting。手动引用计数、手动内存管理。(当多一个使用的时候,程序员手动发送retain消息,当少一个人使用的时候程序猿发送release消息。)
ARC:Automatic Reference Counting 。自动引用计数、自动内存管理。
Xcode默认使用也是ARC(当多一个或者少一个使用的时候,系统自动在合适的地方发送retain、release消息)
MRC虽然麻烦但是面试必考!!ARC底层也是MRC!!
main.m
int main(int argc, char * argv[]) { Person *p1 =[Person new]; NSLog(@"retainCount=%lu",[p1 retainCount]);//新创建的对象引用计数器的值默认是1 [p1 retain];//为对象发送reatin 对象的应用计数器+1 NSLog(@"Count=%lu",p1.retainCount); //为对象发送release消息并不是回收对象,而是对象的引用计数-1 [p1 release];//当引用计数器的值变为0的时候,会自动调用dealloc方法 return 0; }
#import "Person.h" @implementation Person -(void) sayHi{ NSLog(@"HIHI"); } -(void)dealloc{ NSLog(@"我是dealloc方法"); [super dealloc];//重写dealloc方法的时候最后要调用dealloc方法 } @end