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. 何时需要释放
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,逻辑清晰,使用方便。
这仅是我一点粗浅的认识,引用计数这种先进技术的优点需要日后慢慢体会。