一、内存管理的基本概念及范围
1、管理范围:
1)管理任何继承NSObject的对象,对其他基本数据类型是无效的。
因为对象和基本数据类型存储的区域是不一样的。对象存储在需要内存管理的堆区,而基本数据类型存放在栈区。
2)对象类型是程序在运行过程中动态分配的,存储在堆区。
内存管理主要是【对堆区中的对象】的内存管理
二、内存管理的原理和分类
1、对象的所有权及引用计数
1)【所有权策略】
任何自己创建的对象都归自己所有,可以使用名字以“alloc”和“new”开头或名字中包含“copy”的方法创建对象,可以使用retain来获取一个对象的所有权
2)【对象的引用计数】retainCount
每个OC对象都有自己的引用计数器,标示【当前对象】当前有多少个东西在使用这个对象,当该对象被创建时,计数器值为1。
3)【引用计数器作用】
是判断对象要不要回收的依据。
如果引用计数器为0,则就要回收该对象。
【例外】对象值为nil时,引用计数器为0,但不回收空间,因为根本就没分配空间
4、【对引用计数器的操作】
给对象发送消息,进行相应的计数器操作
【retain消息】使计数器+1,该方法返回对象本身
【release消息】使计数器-1,并不代表释放对象
【retainCount消息】获得对象当前的引用计数器值 %ld %lu
5、【对象的销毁】
当一个对象的引用计数器为0时,那么它将被销毁,其占用的内存被系统回收
当对象被销毁时,系统会自动向对象发送一条【dealloc】消息,一般会重写dealloc方法,在这里释放相关的资源。一旦重写了dealloc方法就必须调用[super dealloc],并且放在代码块的最后调用,不能直接调用dealloc方法。
一旦对象被回收,那么他所占据的存储空间就不再可用,坚持使用会导致程序崩溃
【注意】
1)如果对象的计数器不为0,那么在整个程序运行过程中,它所占用的内存就不可能被回收(除非整个程序已经退出)
2)任何一个对象,刚生下来的时候,引用计数器都为1。当使用alloc、new或者copy创建一个对象时,对象的引用计数器默认就是1.
2、OC内存管理的分类
OC中提供了三种内存管理方式:
开发中如何使用:需要理解MRC,但是实际尽量使用ARC
三、手动内存管理入门
【首先关闭ARC】
1、手动管理内存实例
#import
#pragma mark Person类定义部分
@interface Person : NSObject
@property NSString *name;
@property int age;
@end
#pragma mark Person类实现部分
@implementation Person
//对象的临终遗言,对象销毁时,会默认调用该方法
//【注意】该方法是系统根据引用计数器自动调用的,不需要手动调用
-(void)dealloc{
NSLog(@"This person dead....");
//再释放父类
[super dealloc];
}
@end
int main(int argc, const char * argv[])
{
@autoreleasepool {
//用Person类实例化一个对象
Person *p = [Person new];//此时对象的所有者是自己
//证明该对象有一个所有者
NSInteger count = [p retainCount];
NSLog(@"count1 = %lu",count);
//引用计数器+1
//两个指针指向一个对象,但是下面这个方法并不能是计数器+1
Person *p2 = p;
count = [p2 retainCount];
NSLog(@"count2 = %lu",count);
//只有通过retain方法可以使计数器+1
Person *p3 = [p retain];
count = [p retainCount];
NSLog(@"count3 = %lu",count);
//想要回收对象,则要想办法是retainCount从2变成0
[p release];
[p3 release];
//想要证明person对象被释放了,可以重写其dealloc放法
}
return 0;
}
打印结果:
2015-10-06 10:32:56.855 MRCDemo[925:303] count1 = 1
2015-10-06 10:32:56.857 MRCDemo[925:303] count2 = 1
2015-10-06 10:32:56.857 MRCDemo[925:303] count3 = 2
2015-10-06 10:32:56.858 MRCDemo[925:303] This persondead....