8,手动内存管理

来源:互联网 发布:淘宝地址转换 编辑:程序博客网 时间:2024/06/11 08:08

1.oc内存管理的特点
Objective-C的内存管理机制与.Net/Java那种全自动的垃圾回收机制是不同的,它本质上还是C语言中的手动管理方式,只不过稍微加了一些自动方法。
在没有autorelease的情况下,oc和c/c++一样,自己申请,自己释放,内存管理完全自己掌控。
oc中每一个对象有一个引用计数,表示有多少个指针引用了这个对象,当引用计数为0的时候,系统就会销毁这个对象。
通过retain, release来手动加减引用计数。

2.autorelease作用
作用在于将release的调用延迟,对于每一个Autorelease,系统不会立即将其计数减一。只是把该Object放入了当前的Autoreleasepool中,当该pool被释放时,该pool中的所有Object会被调用Release,计数才会减一。所以说是起了一个延迟release的作用

3.Autoreleasepool作用
一句话来说就是避免频繁申请/释放内存。
Autoreleasepool是一个自动释放池(NSAutoreleasePool对象,它是一个数组),其中包含了许多等待release的对象。系统中有很多个Autoreleasepool。
Autoreleasepool分手动和隐式创建。所有Autoreleasepool组织为一个栈结构。
每进入一个新的runloop,就会在栈顶创建一个Autoreleasepool。结束一个runloop就会销毁这个Autoreleasepool。
一个UI事件,Timer call, delegate call,都会是一个新的Runloop。oc至少保证method安全的,也就是一个块至少新建一个runloop
销毁一个Autoreleasepool的时候,并不一定会销毁其中所有对象,而是对他们全部做一次release。(遍历这个数组)只有release后计数为0的对象才会被销毁
优点:autorelase的对象是不可控的,它有隐式创建的pool决定,但它的好处是可以做到每个函数对自己申请的对象负责,自己申请,自己释放,该函数的调用者不需要关心它内部申请对象的管理。在下面这个例子中,Fun1调用Fun2,Fun1不需要关心obj的释放问题,也就是说Fun2自己申请的对象自己负责释放。不用调用者Fun1操心

ClassA *Fun2()

{

ClassA *obj = [[[ClassA alloc]init]autorelease];

return obj;

}

4.默认autorelease的对象
5.总体原则(以块为单位(因为pool是块为单位))
对象的引用计数为0了以后,会调用对象的delloc方法,在这个方法中,对象需要将自己所包含的实例变量(类空间变量)release。并调用父类的delloc方法。
autorelease缺点:
在iphone/ipad等内存有限的手持设备上,并不建议 使用autorelease,因为说到底这是一种延时释放,如果你的程序一直在跑,代码尚未执行到[pool release]之前,即使有很多对象不再需要了,但它们占用的内存并未真正释放。
不要把大量循环操作放到同一个NSAutoreleasePool之间,道理同上,这样会使池中有大量对象,导致程序在运行时占用较多内存。
(1)谁创建,谁释放
谁retain,谁release。只要你调用了retain,无论这个对象是如何生成的,你都要调用release。有时候你的代码中明明没有retain,可是系统会在默认实现中加入retain。
普通变量,使用alloc,new ,copy创建的对象要么加上autorelease,要么在块结束的时候release.
在类和类的方法中定义的变量要么使用autorelease,要么在类的dealloc方法中release它们。
(2)除了alloc、new或copy之外的方法创建的对象都自动声明了autorelease。(stringWithstring等合成的创建方法)
一个例外是NSString对象由系统自动管理,它的count是很大的数,release了也不会有效果。
(3) release一个指针后,应该立即把指针清空(nil),对一个空指针release或者给空指针传消息是合法的。给非空指针(但消息不响应或者指向内存无效已释放)则crash
(4)在一个函数中创建并返回对象,需要把这个对象设置为autorelease(上例),因为调用者Func1不用关心obj的释放问题。
(5)类的dealloc方法作用是统一对类空间作用域的变量(实例变量)做release(不是包括方法中的局部变量),需要调用[super dealloc];
(6)赋值的时候,内置变量,retain,copy三者处理计数方法不同。内置变量不用考虑计数问题.obj1=obj2;if(obj2!=nil)
retain是指针复制(浅复制),需要[obj1 release], obj1= [obj2 retain];
copy是对象复制(深复制),[obj1 release],obj1 = [obj2 copy]      obj2需要实现NScopying协议,对initwithcopy进行实现。
(7)属性就是为实例变量自动编写 set/get方法,用于将成员作为public。如outlet的变量,多个函数会用到的变量。
(8)sysn的作用是重命名属性所对应的实例变量的名字,默认是下划线+属性作为变量名。set/get函数不加下划线。
(9)经常使用self来区分使用的是属性(对应的方法)还是直接使用变量(属性对应的实例变量)
(10)NSAutoreleasePool 和autoreleasepool区别
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init;
// Code benefitting from a local autorelease pool.
[pool release];
you would write:
@autoreleasepool {
// Code benefitting from a local autorelease pool.
}
@autoreleasepool blocks are more efficient than using an instance of NSAutoreleasePool directly; you can also use them even if you do not use ARC.
用arc的话必需用@autoreleasepool,不用ARC的话,也可以用@autoreleasepool,你明白了没?
因为用@autoreleasepool比NSAutoreleasePool少写一行字,在中间return的时候也不考虑是否要释放pool,so ,我一直用它哟:)

原创粉丝点击