2010-07-06 78 views
2

在iPhone上使用obj-c时,是否会在释放所有内容时自动释放?在iPhone上使用obj-c时,是否会在释放所有内容的同时自动释放?

例如,此代码:

NSString *recipe = [[NSString alloc] initWithUTF8String:sqlite3_column_text(dbps,0)]; 
[arr addObject:recipe]; 
[recipe release]; 

可通过自动释放配方的NSString当我创建它缩短为两行:

NSString *recipe = [[[NSString alloc] initWithUTF8String:sqlite3_column_text(dbps,0)] autorelease]; 
[arr addObject:recipe]; 

有什么缺点呢?我觉得它更适合我的编码风格。谢谢大家。

回答

6

缺点是对象稍后被释放。在大多数情况下,这不会成为问题,但如果您在紧密循环中分配和自动释放数千个对象,则这种开销可能会加剧它对性能的影响,甚至导致应用程序内存不足。

在任何情况下,你可能想使用:

[NSString stringWithUTF8String:sqlite3_column_text(dbps,0)]; 

,而不是

[[[NSString alloc] initWithUTF8String:sqlite3_column_text(dbps,0)] autorelease]; 
+0

+1用于提及返回自动释放对象的现有类方法。请参阅Brent Simmon关于此主题的博客文章。 http://inessential.com/2010/06/28/how_i_manage_memory – falconcreek 2010-07-06 13:36:30

+0

这种方法可能更容易阅读和输入,但最终你仍然有一个自动释放的对象,直到当前的自动释放池完成它的工作才会被释放。 – 2010-07-06 15:44:57

-2

问题是,当你自动释放你没有真正释放对象,但将它添加到当前自动释放池。当释放每次通过主循环完成的池时,对象将被有效释放。

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
int retVal = UIApplicationMain(argc, argv, nil, nil); 
[pool release]; 

你可以创建你自己的autorelease池,但我不确定它会比简单地使用release更好。

+0

默认的自动释放池每次通过主运行循环被排空。 – Brian 2010-07-06 13:32:20

+0

我不确定这一点;)感谢纠正! – Charter 2010-07-06 13:42:35

2

如果对象在其使用的函数之外没有作用域,则应始终释放它以尽量减少应用程序使用的内存量。

如果让对象继续存在,直到autorelease池启动,则可能需要分配大量不需要的内存。这对iOS 4和快速应用切换尤其重要,其中内存也分配给后台的应用。

你自己的内存占用越低,在内存越来越紧张的情况下,你的应用程序在后台不会被终止的可能性越大。

+1

不是特别准确 - 每次通过运行循环时都会释放autorelease池,所以当您的应用程序停止运行时,您将释放所有内存,并手动处理内存碎片(无论如何您都无法控制)。 – 2010-07-06 14:16:11

+0

@tc:对,我的错。实际上,大量自动发布的对象可能会导致后台应用程序被终止,以便为您的应用程序提供足够的内存。 – 2010-07-06 15:41:40

1

这是我关于这个问题的认识,我敢肯定,如果我说什么错了,我会得到downvoted死亡;)

  1. 一般来说,在紧密循环,init + release会比快autorelease。大多数情况下,性能不是问题
  2. 您可能并不总是想要autorelease。如果你想要一个对象继续存在,你需要手动release或者将你的自动释放对象放在一个带有retain的属性中,这样你就可以稍后获得它,否则只要它超出范围
  3. 就会被释放
  4. 具有手动init + release你有过正在发生的事情更为精细的控制,这可能(尤其是现在的GCD是很普遍的)是先进的多线程的情况下非常有用
  5. autorelease可能是罚款的大部分时间,只要你明白reference counting是如何工作的,但不要把它当作银弹。您仍然可以使用autorelease错误地泄漏大量内存。
+0

我不确定你在这里使用多线程是什么意思 - release比autorelease没有任何主要优势。 – 2010-07-06 14:17:20

1

我会改过来的问题:主要缺点release是,它很容易忘记。分配到本地或实例变量看起来几乎是相同的(他们是完全相同的,如果你没有在初始分配):

  • Foo * a = [[Foo alloc] init];
  • myFoo = [[Foo alloc] init];

这和类似的问题,导致一堆潜在的问题:

  • 当你复制并粘贴代码时,你会忘记发布吗?
  • 当你在本地和实例变量之间切换时,你会记得添加/删除发布吗?
  • 如果抛出异常,代码是否泄漏? (这几乎总是如此,但传统上不关心Obj-C中的异常)

就个人而言,重构代码时内存泄漏的开销比少数自动释放对象的开销更糟。我偶尔会重构代码,以便它看起来像这样:

FooView * v = [[[FooView alloc] initWithFrame:CGRectZero] autorelease]; 
// set up v... 
myFoo = [v retain]; 
  • 局部变量是稍微更高效。
  • 如果您决定不再需要实例变量,则只需注释掉一行。
  • 意见是相当重量级的,所以自动释放开销不会多大关系

为了完整起见,如果你在一个循环中(例如,测试代码)做了一堆东西,你可以在自动释放每次迭代的是这样结尾:

for (size_t n = 100000; n--;) { 
    NSAutoreleasePool * pool = [NSAutoreleasePool new]; 
    // ... allocate and autorelease some stuff ... 
    [pool release]; pool = nil; 
} 

如果你担心的效率,可以使用(例如)CFString字符串函数获得显著的加速 - Objective-C的开销是小弦相当显著。