因为我们之前手工通过retain给h1引用的对象增加了一个引用,导致即使[pool drain]也没有销毁对象
所以说AutoreleasePool并没有帮我们真正的把池中的对象销毁,只是给池中对象逐个调用release而已。
再以图片的形式看看内存中发生的事情
C#妹妹:这样看下来,自动释放池并没有解决什么问题呀?不是还要我们自己管理引用数量么?
Objective-C阿姨:确实还是需要我们自己统计引用数量,但是可以帮我们从乱七八糟的release中解脱出来。只需要release池对象就好了,其他对象也就跟着被release了
01 int main (int argc, const char * argv[])
02 {
03 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];//建立一个自动释放池 pool
04 House *h1=[[House new] autorelease];
05 House *h2=[[House new] autorelease];
06 House *h3=[[House new] autorelease];
07 House *h4=[[House new] autorelease];
08 NSLog(@"%lu,%lu,%lu,%lu",[h1 retainCount],[h2 retainCount],[h3 retainCount],[h4 retainCount]);
09 //h1-h4经过某些运算完成了历史使命
10 [pool drain];
11 return 0;
12 }
13
上面的代码肯定比下面的这些更清爽点
01 int main (int argc, const char * argv[])
02 {
03 House *h1=[House new];
04 House *h2=[House new];
05 House *h3=[House new];
06 House *h4=[House new];
07 NSLog(@"%lu,%lu,%lu,%lu",[h1 retainCount],[h2 retainCount],[h3 retainCount],[h4 retainCount]);
08 //h1-h4经过某些运算完成了历史使命
09 [h1 release];
10 [h2 release];
11 [h3 release];
12 [h4 release];
13 return 0;
14 }
15
C#妹妹:貌似是少调用了些release,但是毕竟没有release灵活啊,如果是release,一旦程序员决定不在使用的对象,马上就可以释放掉,但是AutoreleasePool必须要等到最后一起drain。说白了也就是延长了垃圾的生存时间,浪费了内存。
Objective-C阿姨:一点不假,所以在移动设备上比如iPhone,iPad,为了节约宝贵的内存资源,不建议使用自动释放池。即便在Mac上运行的程序,如果有太多的对象生成,也可以多次生成释放或嵌套对象池来尽早释放对象。比如下面的例子
01 int main (int argc, const char * argv[])
02 {
03 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
04 int i;
05 for(i=0;i<1000000000;i++)
06 {
07 House *h=[[House new] autorelease];
08 if(i00==0)//如果没有这个if语句里边的内容,所有1000000000个对象要全部生成完毕才能全部释放
09 {
10 [pool drain];
11 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
12 }
13 }
14 [pool drain];
15 return 0;
16 }
17
比如上面的代码,如果没有if语句里边的内容,所有1000000000个House对象都要等到全部对象生成完毕,程序结束的时候才能全部释放
内存消耗量非常大
但是加了这个if语句,每生成1000个对象,销毁一次,内存占用就非常小。
咳,十亿套房子要真的就这么生成了,非气死那些开发商不可。。。
C#妹妹:
Objective-C阿姨:说了半天,还没有说自动释放池最重要的用法。
C#妹妹:最重要??你认为有人会耐着性子把咱俩的对话看到这个地方么?
Objective-C阿姨:刚才说嗨了,重点忘记了。也许有那么1-2人能耐着性子看到这里吧,大部分人早把网页关闭了。看下面的例子
01 #import "House.h"
02 //先建一个需要被删除的对象 House类
03 @implementation House
04 -(void) dealloc//Objective-C在销毁对象的时候会自动调用这个方法
05 {
06 NSLog(@"房子被拆除了");
07 [super dealloc];
08 }
09 -(NSString*)description
10 {
11 NSString *desc=[[NSString alloc] initWithFormat:@"世界上最便宜的房子"];
12 return desc;
13 }
14 @end
15
我修改了一下House类,添加了一个description方法,返回一个NSString对象,
description相当于.NET中的ToString()方法,其实也是基类NSObject定义的,子类可以重写,用来返回描述该类的字符串。
我这里重新了description,返回NSString对象,但是这个NSString对象该如何销毁呢?该由谁来负责release呢?
显然这个工作只能由调用description的程序来完成
C#妹妹:废话,要是在description里边就销毁了,还返回个屁结果啊
Objective-C阿姨:那就看下面的例子吧。
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
House *h1=[[House new]autorelease];
NSString *desc=[h1 description];
NSLog(@"%@",desc);
[desc release];
[pool drain];
return 0;
}
这样用起来毕竟不直接
如果在House的description中使用autorelease,比如代码修改为
NSString *desc=[[NSString alloc] initWithFormat:@"世界上最便宜的房子"];
return [desc autorelease];
调用House的description的程序就可以更简洁
1 int main (int argc, const char * argv[])
2 {
3 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
4 House *h1=[[House new]autorelease];
5 NSLog(@"%@",[h1 description]);
6 [pool drain];
7 return 0;
8 }
9
C#妹妹:今天好像好像晕了??感觉越来越复杂了~~,程序员管理内存还真是很辛苦??
Objective-C阿姨:今天说了太多的技术,因为没有规则来约束他们,所以感觉好像杂乱无章,下次会有内存管理的章法,只要遵循几个简单的原则,其实是非常简单的。下次再聊哇。。。
--
各位同学,本人学习Objective-C时间很短,学习Objective-C其实不是为了Mac、iPhone开发,并没有实用,
其实是一个C#用户学习Objective-C的学习笔记,学习的确切目的是帮助我理解C#,毕竟没有比较是不可能知道所谓C#的特点的
请大家批判的眼光看这个东西,如果发现和其他文章、书籍、评论、资料有冲突,请尽量以其他文章为准。并给我留言
也邀请所有高手积极拍砖,我正好用来盖房子~~~
《C#妹妹和Objective-C阿姨对话录》
转自新浪博客http://blog.sina.com.cn/s/blog_894e62750100zqiw.html