iPhone上有了obj-c,自动删除所有内容而不是发布有什么害处吗?

iPhone上有了obj-c,自动删除所有内容而不是发布有什么害处吗?,iphone,objective-c,Iphone,Objective C,iPhone上有了obj-c,自动删除所有内容而不是发布有什么害处吗 例如,该代码: NSString *recipe = [[NSString alloc] initWithUTF8String:sqlite3_column_text(dbps,0)]; [arr addObject:recipe]; [recipe release]; 通过在创建配方字符串时自动删除配方字符串,可以将其缩短为两行: NSString *recipe = [[[NSString alloc] initWith

iPhone上有了obj-c,自动删除所有内容而不是发布有什么害处吗

例如,该代码:

NSString *recipe = [[NSString alloc] initWithUTF8String:sqlite3_column_text(dbps,0)];
[arr addObject:recipe];
[recipe release];
通过在创建配方字符串时自动删除配方字符串,可以将其缩短为两行:

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

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

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

在任何情况下,您都可能希望使用:

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

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

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

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

您可以创建自己的自动释放池,但我不确定这是否比简单地使用release更好。

如果对象在其使用的函数之外没有作用域,您应该始终释放它,以最小化应用程序所消耗的内存量

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


您自己的内存占用越低,您的应用程序在后台运行时不被终止的可能性就越大,以防内存紧张。

这是我对这个问题的理解,我相信如果我说错了什么,我会被否决的;)

  • 一般来说,在紧循环中,
    init
    +
    release
    将比
    autorelease
    更快。大多数情况下,性能不是问题
  • 实际上,您可能不想一直
    自动释放
    。如果你想让一个对象粘在周围,你需要手动
    释放
    或将自动释放的对象粘在一个带有
    保留
    的属性中,这样你以后就可以得到它,否则一旦对象超出范围,它就会被释放
  • 通过手动
    init
    +
    release
    您可以对正在发生的事情进行更细粒度的控制,这对于高级多线程场景可能很有用(尤其是现在GCD已经普及)
  • autorelease
    只要您了解其工作原理,在大多数情况下都是可以的,但不要将其视为一颗灵丹妙药。使用
    autorelease
    时仍可能错误地泄漏大量内存

  • 我将把问题转过来:
    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;
    }
    
    • 局部变量的效率略高
    • 如果您决定不再需要实例变量,只需注释掉一行即可
    • 视图相当重,因此自动释放开销不会有多大影响
    为了完整性,如果您在循环中执行一系列操作(例如,测试代码),您可以在每次迭代结束时使用以下内容自动释放:

    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开销相当大。

    默认的自动释放池每次都会通过主运行循环耗尽。+1用于提及返回自动释放对象的现有类方法。请参阅布伦特·西蒙(Brent Simmon)关于这一主题的博客文章。此方法可能更易于阅读和键入,但最终你仍然拥有一个自动释放对象,在当前自动释放池完成其工作之前,该对象不会被释放。不太准确-自动释放池在运行循环的每一次过程中都会被释放,因此当你的应用程序后台运行时,你已经释放了所有内存,手工处理诸如内存碎片之类的东西(你无论如何都无法控制)。@tc:是的,我的错。实际上,在另一种情况下,大量的自动释放对象可能会导致后台应用程序终止,以便为您的应用程序提供足够的内存。我不确定这里的多线程是什么意思-与自动释放相比,释放没有任何主要优势。