天天看点

IOS开发基础Object-C(07)—OC内存管理(1)-retain和release

前面我们已经说过,OC不同于Java的地方就是没有垃圾回收机制,在内存管理这块,cocoa引入了一种称为引用计数(reference counting)的技术,有时也叫保留计数,每个对象有一个与之对关联的整数,称作它的引用计数器或保留计数器.当某段代码要访问一个对象的时候,该代码将该对象的保留计数值加1,表示”我要访问该对象”,当这段代码结束对象访问时,将对象的保留计数值减1,表示它不再访问该对象,当保留计数值为0时,表示不再有代码访问对象了,对象被销毁,其占用的内存被系统回收。

我来简单说一下原理:

1、每个对象内部都保存了一个与之关联的整数,称之为引用计数器,当使用alloc、new或者copy创建一个对象时,对象的引用计数器被设置为1;

2、给对象发送一个retain消息(调用retain方法),可以使计数器+1;

3、给对象发送一个release消息(调用release方法)或者autorelease消息,可以使计数器-1;

4、当一个对象的引用计数为0时,那么他将被销毁,其占用的内存被系统回收,OC也会自动向对象发送一条dealloc消息,一般会重写dealloc方法,在这里释放相关资源,一定不要直接调用dealloc方法。

5、发送retainCount消息获得当前的引用计数器的值。

注:我们这里说的发送消息就是调用方法

- (id)retain; // 计数器+1

- (void)release; //计数器-1

- (id)autorelease;//计数器-1

- (unsigned)retainCount;//获得当前引用计数器的值

在这里大家就会疑惑了,怎么的对象才需要我们管理内存呢?可以这么说,任何继承了NSObject的对象都需要管理内存。基本数据类型,像int ,float,double,int类型的指针数组什么的都不需要管理内存。

我们来看一下例子依照惯例,我们还是来创建一个类:

Student.h

#import<Foundation/Foundation.h>
@interface Student :NSObject
@property int age; //声明一个getter方法、setter方法
@end
           

Student.m

#import "Student.h"
@implementation Student

@synthesize age=_age; //在xcode4.5环境下可以省略

//验证对象有没有被回收
-(void)dealloc
{
    NSLog(@"%@被销毁了",self);//验证对象有没有被回收
    [super dealloc];//一定要到调用super的dealloc方法,而且最好是在最后调用
}
@end
           

我们在main.m中测试一下

#import<Foundation/Foundation.h>
#import"Student.h"

int main(int argc,const char *argv[])
{
    @autoreleasepool{
         Student *stu=[[Student alloc]init];//调用了alloc方法,计数器为1
         [stu release];//释放,计数器为0;
        }
    return ;
}
           

在前边我们有提到,在销毁对象的时候,OC也会自动向对象发送一条dealloc消息,一般会重写dealloc方法,在这里释放相关资源,一定不要直接调用dealloc方法。所以我们用dealloc方法来验证对象是否被销毁。

如果对象被回收以后(retainCount=0),再发送一条release消息,就会发生野指针错误。

#import<Foundation/Foundation.h>
#import"Student.h"

int main(int argc,const char *argv[])
{
    @autoreleasepool{
         Student *stu=[[Student alloc]init];//调用了alloc方法,计数器为1
         [stu release];//释放,计数器为0

         [stu release];//计数器为0,再次释放则会发生野指针错误,也就是说访问了你不该访问的内存
        }
    return ;
}
           

autorelease的实现

还有一种情况,如果方法名并不以alloc、new、copy开头,比如:

+ (NSArray *)array  
{  
    return [[NSArray alloc] init] autorelease];  
}  
           

程序内部调用了alloc,就需要调用release来释放,所以我们采用了一种自动释放机制autorelease,其中具体原理先不深究,后面我会详细讲解。

内存管理原则:

1、谁创建,谁释放(“谁污染,谁治理”),如果你通过alloc、new或者copy来创建一个对象,那么你必须调用release或者autorelease来释放,换句话说,不是你创建的,你就不用释放

2、一般来说,除了alloc、new或者copy之外的方法创建的对象,都被声明了autorelease

3、谁retain,谁release,无论这个对象是怎样生成的

视频链接

http://pan.baidu.com/s/1ntMpRQT

继续阅读