objective-C引用计数的使用心得

Objective-C有不只一种内存管理方式,我这里只讨论引用计数相关内容。

1. 在堆上分配对象

所有对象(不知道有无例外)都用堆方式分配内存,也就像c++中的new,对象引用都使用指针啦,很统一。

2. 指针赋值

将一个对象直接赋值给另一个,都是赋值指针,若不做特殊操作,人家释放掉后,你就惨了,野指针。后面重点讨论“特殊操作”

3. copy方法

obj1 = [obj2 copy];如此使用后,系统为obj1新申请一块内存,拷贝了obj2的内容,以后个不相关了。

4. 引用计数

每个对象有一个引用计数,当引用计数为0时,对象自动销毁,如下几个操作可以改变引用计数。

a,创造对象,引用计数默认为1

b,向对象传retain消息,引用计数+1

c,向对象传release消息,引用计数-1

d,向对象传autorelease消息,将来某个时候应用计数-1

所有引用计数增加和减少必须配对,谁加谁就负责减,权责明确。若增加多了,会造成内存泄漏,若减少多了,指针就野啦,将来某时刻就得崩溃。

5. return对象

c++中经典错误是在return在某函数中栈式分配的一个对象地址,函数返回后该对象地址失效,将来某一时刻被其它数据覆盖。若在对上分配对象,使用者很可能忘记释放,造成内存泄漏。

objC的习惯是堆分配,autorelease,然后返回,这样基本万无一失。

Class2 * obj1 = [[Class1 alloc] init];

[obj1 autorelease];

return obj1;

6. 何时需要释放

a,向某对象发retain消息了

b,调用alloc,copy和new返回的对象

记住,b是惯例,其它方法内部都会autorelease一下,别没事不按套路出牌,自己写个另类方法,不autorelease。

7. 如何使用对象

a,只用一下,用完不管,跟c传指针一样

b,需要长时间引用,拿到一个对象后,若需要保存一段时间,可以retain一下,防止这个对象被释放,但可以被别人修改。

c,copy一下,直接新做了一个,与之前的毫无关系,这样既不会被别人释放,也不会被别人修改

d,创造一个对象,用init或者new

a类不需要release,其他都需要release一下

8,关于属性

声明属性时可以加上retain关键字,例如@property(nonatomic, retain),这样属性默认实现方式是release原对象,retain形参对象,然后复制给成员对象,如下所示。

setValue:(class1)obj1

{

if(obj != obj1)

{

[obj release];

[obj1 retain];

obj = obj1;

}

}

在类方法中直接使用成员变量名时代表该变量,前面加self.时调用的是属性,这是有区别的

比如self.obj = nil;就会将obj release一下,然后赋值nil,而obj=nil;则直接赋值nil,内存泄漏了。

---分割线-----------------------------------------------------------

最后说说使用感受

如果讲申请和释放资源问题看作一个决策问题的话,那么objc的引用计数方式将全局决策局部化,将求全局最优解转成求局部最优解问题。

c++中new和delete方式,只有一次分配,一次释放。优点是分配释放次数少,不忘记就不会泄漏,虽然不如smartpoint和垃圾回收方便,但在该方面也不会比objC的引用计数差。

new和delete的问题是合适delete。因为必须确定大家都不用时才能delete,这个机会不好把握,很容易出错,到处野指针。而ObjC繁琐的引用计数机制正好可以克服该缺点,老子的事老子负责,别人我不管,我用了我就retain,我不用我就release,逻辑清晰,使用方便。

这仅是我一点粗浅的认识,引用计数这种先进技术的优点需要日后慢慢体会。