2010-11-06 20:28:12| 分类: objective c | 标签: |举报 |字号大中小 订阅
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
评论