Objective-c 内存管理

我们在程序当中,必须能够聪明地去使用内存。特别是在移动平台上,我们要尽量避免程序无谓地去占有系统内存。

Objective-c中,有很好地内存管理机制,即引用计数(reference count),用来管理内存。当然,现在由于ARC(Automatic Reference Counting)地使用,在很多情况下,我们不用去再进行retain/release等内存管理,但是了解objective-c的内存机制仍然很重要

1. 自动释放池(AutoReleasePool)

自动释放池用来跟踪程序当中创建的对象,当在释放pool的时候,释放这些对象。

    NSAutoreleasePool* pool = [[NSAutoreleasePoolalloc]init];//创建自动释放池

    [pooldrain]; //释放自动释放池

[object autorelease];//将对象objective添加到自动释放池中

2.引用计数(Reference Count)

首先,我们思考为什么会有引用计数的工作原理。我们在程序中,通过alloc来为对象进行内存分配。而程序在运行中时,可能会有多个位置引用某个我们创建的对象(例如在数组中添加了这个对象),我们必须要确定在使用该对象的每个人都使用完之后,才能释放掉这个对象占用的内存空间。所以我们采用引用计数来记录下引用当前对象的位置的数目,这样当只要因为计数不为0时,那么程序就不会释放掉这个对象的内存。


语句:

alloc:创建对象,分配内存空间,将其引用计数设为1

copy:复制对象,同时设置新对象的引用计数为1

retain;引用计数+1

添加到任何的集合类:引用计数+1

release:引用计数-1

autorelease:将对象添加到自动释放池,但不释放,在之后进行释放

dealloc:释放这个对象占用的内存(我们不会显式调用)


我们将对象添加到任何类型的集合中时,将其引用计数+1;这样是为了当我们在之后对这个对象进行release的时候,集合当中仍保留着对该对象有效的引用。

int main(int argc,const char * argv[])

{


    @autoreleasepool {

        NSMutableArray* array = [NSMutableArrayarray];

        NSMutableString* str1 = [[NSMutableStringalloc]initWithString:@"it's str1"];//用alloc进行创建

        NSLog(@"the retain count is %lx",[str1retainCount]);

        [arrayaddObject:str1];//添加到array数组中

        NSLog(@"after added to array is %lx",[str1retainCount]);

        [str1retain]; //retain

        NSLog(@"after retain is %lx",[str1retainCount]);

        [str1release]; //release

        NSLog(@"after release is %lx",[str1retainCount]);

        [arrayremoveAllObjects];//移除该对象

        NSLog(@"after removed from array is %lx",[str1retainCount]);

        [str1release]; //再次release

       NSLog(@"last is %lx",[str1retainCount]);

    }

    return 0;

}

输出为

the retain count is 1

after added to array is 2

after retain is 3

after release is 2

after removed from array is 1

last is fffffffffffffff



根据这个例子,应该就对引用计数的整体方法有了掌握。另外[str1 retainCount]这个方法不推荐使用,具体情况可以到http://whentouseretaincount.com查看,里面最醒目的一个词,never永远都不要使用这个方法。


3. 引用计数(reference count)和实例变量(instance variable)

a.

-(void)setName:(NSString *)theName{

   name = theName;

}

b.

-(void)setName:(NSString *)theName{

    [name release];

    name = [[NSStringalloc]initWithString:theName];

}

主要看看a和b的区别,a是直接进行赋值操作,b是现将之前的name释放掉,然后再创建一个新的对theName的复制。很显然,b要好于a。a是不推荐的做法,因为a是直接传递的指针,即name和theName指向同一个地址块,这样这个方法所在的那个类就不具备对name的掌控权,因为外面的方法直接操控theName就对name也同样进行了修改,显然,对于数据的封装,是不希望看到这种情况发生的。而且当外部的theName被释放掉之后,name为指向一个无效的地址空间。所以推荐使用b方法,即使当你是使用ARC进行编程时,也应该注意,我们要为变量创建副本,而不是直接的指针的指向。

4. 一些进行内存管理的基本原则

1. 在代码中,有copy+alloc+retain = release+autorelease;这样的使用次数的对等关系
2. 使用便利构造器(NSString stringwithstring),创建的对象,默认为autorelease的,也就是说,我们不用将其release,release了也没用









  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值