iPhone上有了obj-c,自动删除所有内容而不是发布有什么害处吗?
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
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:是的,我的错。实际上,在另一种情况下,大量的自动释放对象可能会导致后台应用程序终止,以便为您的应用程序提供足够的内存。我不确定这里的多线程是什么意思-与自动释放相比,释放没有任何主要优势。