注册 登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

vs-yanguo的博客

 
 
 

日志

 
 
 
 

Objective-C 内存管理  

2010-11-06 20:28:12|  分类: objective c |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |


Objective-C中内存管理使用保留计数(retain count),基本原则是一个对象(object)的保留计数如果大于0,那么这个对象存在,如果等于0,则系统自动删除,相当于没妈的孩子。一个对象可以有多个拥有者(owner)(不好意思,前面举了个很不恰当的例子,一个孩子不能有多个妈...),当对象有多个拥有者时保留计数就大于1。
跟内存管理有关的关键字也就alloc, copy(包含copy的词),release,autorelease,retain等。
根据保留计数的概念,alloc,copy和retain都会使保留计数+1,release和autorelease会使保留计数-1。如下图:

release和autorelease 的区别就是release将立即将保留计数-1,而autorelease现在不减但在以后的某个时候会-1,相当于延迟发生的release。
当一个数组销毁时,其子元素如果没有其他拥有者将全部被销毁。
不能将release等用于C++中delete的概念,release并不直接将对象删除,只是将对象的保留计数-1,如果对象保留计数减为0,则系统自动删除该对象。
创建对象
创建对象有两种方式,手动管理对象的生成与销毁,即使用alloc和release。或者使用一种叫类函数的初始化函数。
NSString *string;
string = [[NSString alloc] initWithString:@"Hello"];
NSLog(string);
[string release];
使用alloc与C++的new,delete类似,必须与release或者autorelease配对使用。
NSString *string;
string = [NSString stringWithFormat:@"Hello"];
NSLog(string);
使用类函数则不用手动release,相当于调用了alloc和autorelease。
在函数中返回对象
在函数中返回对象时要保证返回时对象还存在,返回后对象不会立即销毁。
- (NSString *)fullName {
    NSString *string = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
    return string;
}
- (NSString *)fullName {
    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@", firstName,
lastName] autorelease];
    return string;
}
这两种方法都是对的,使用autorelease保证返回时对象还能使用,但会在未来的某个时候自动销毁。
下面的方法就是错的:
- (NSString *)fullName {
    NSString *string = [[[NSString alloc] initWithFormat:@"%@ %@", firstName,
lastName] release];
    return string;
}
返回string时,string已经被销毁,所以无法返回。
- (NSString *)fullName {
    NSString *string = [[NSString alloc] initWithFormat:@"%@ %@", firstName,
lastName];
    return string;
}
返回string后,string不会被销毁,造成内存泄露。

Autorelease Pool
内存池,用来管理autorelease自动销毁的对象。当一个循环(loop)中会创建很多临时对象时,可以在循环内创建内存池来清除每次循环的临时对象。
void main()
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSArray *args = [[NSProcessInfo processInfo] arguments];
    for (NSString *fileName in args) {
        NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
        NSError *error = nil;
        NSString *fileContents = [[[NSString alloc]
initWithContentsOfFile:fileName
                                           encoding:NSUTF8StringEncoding
error:&error] autorelease];
        
        [loopPool drain];
    }
    
    [pool drain];
    exit (EXIT_SUCCESS);
}
从上面的例子可以看到,内存池是可以嵌套使用的。内存池在内存中是用堆(stack)实现的,最内层的池在堆的最顶端,所以释放的顺序就是从里到外的。一旦释放了外层的池,内层的池也自动释放了。内存池使用drain关键字来释放。


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/boboboa32/archive/2010/08/28/5845631.aspx

  评论这张
 
阅读(254)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018