使用iPhone上的obj-c,自动释放所有内容而不是释放是否有任何伤害?

时间:2010-07-06 13:18:58

标签: iphone objective-c

使用iPhone上的obj-c,自动释放所有内容而不是释放是否有任何伤害?

例如,这段代码:

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

当我创建配方nsstring时,可以通过自动释放配方nsstring缩短为两行:

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

这有什么缺点吗?我发现它更适合我的编码风格。谢谢大家。

5 个答案:

答案 0 :(得分:6)

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

无论如何,您可能想要使用:

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

而不是

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

答案 1 :(得分:2)

如果对象的作用域之外没有作用域,则应始终将其释放,以最大限度地减少应用程序消耗的内存量。

如果让对象一直存在,直到自动释放池启动,可能需要分配大量不需要的内存。这对于iOS 4和快速应用切换尤为重要,其中内存也分配给后台的应用程序。

你自己的内存占用越低,你的应用程序在后台运行时不会被终止的可能性越大。

答案 2 :(得分:1)

以下是我对这个问题的理解,如果我说错了,我肯定会被判处死刑;)

  1. 一般来说,在紧密循环中,init + release将比autorelease更快。大部分时间表现都不是问题
  2. 您可能实际上并不想autorelease。如果你想要一个物体,你需要手动release或将你自动释放的obj粘贴在一个retain的属性中,以便你以后可以获得它,否则你的obj将被释放为一旦超出范围
  3. 使用手动init + release,您可以更好地控制正在发生的事情,这对于高级多线程场景(特别是现在GCD普遍存在)非常有用。
  4. autorelease大部分时间都可能很好,只要你理解reference counting是如何工作的,但不要把它当成银弹。您仍然可以使用autorelease错误地泄漏大量内存。

答案 3 :(得分: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开销对于小字符串非常重要。

答案 4 :(得分:-2)

问题是当你进行自动释放时,你实际上并没有释放该对象,而是将其添加到当前的自动释放池中。当你释放每次通过主循环完成的池时,对象将被有效释放。

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

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