six*_*ude 7 memory iphone objective-c
我只是阅读实用内存管理指南.
我对这段代码感到有些困惑:
- (void)printHello {
NSString *string;
string = [NSString stringWithFormat:@"Hello"];
NSLog(@"%@", string);
}
Run Code Online (Sandbox Code Playgroud)
在我看来,字符串的引用计数为0.这是真的吗?
什么阻止字符串在我们打电话之前被解除分配NSLog(string)?
这在某种程度上等同于此:
- (void)printHello {
NSString *string;
string = [[[NSString stringWithFormat:@"Hello"] retain] autorelease];
NSLog(@"%@", string);
}
Run Code Online (Sandbox Code Playgroud)
编辑:类似地,此代码在实用内存管理 指南中给出:
- (NSString *)fullName {
NSString *string = [NSString stringWithFormat:@"%@ %@", firstName, lastName];
return string;
}
Run Code Online (Sandbox Code Playgroud)
何时以及如何释放返回值?谁是老板?调用者是否fullName需要释放全名返回的字符串?
首先:
NSLog(string);
Run Code Online (Sandbox Code Playgroud)
不要这样做.(我刚刚意识到它来自Apple文档.很奇怪.)第一个参数NSLog是格式化字符串.如果你string包含一些百分之百的逃脱,那么坏事就会发生.正确的,如果稍长的方式是:
NSLog(@"%@", string);
Run Code Online (Sandbox Code Playgroud)
现在到了这一点:自动释放的对象没有零保留计数.他们保留计数1+并且对他们进行挂起的-1操作,这将在"未来很快"发生.
"很快将来"的确切含义取决于具体情况.如果您在主线程上并且没有其他自动释放池,则自动释放的对象将在下一个runloop迭代中释放.如果您有其他发布池,则不必如此:
// Let’s pretend this is a long loop and you don’t want to wait
// for the autoreleased objects to be collected by the main pool.
for (…) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *foo = [NSString stringWith…];
[pool drain];
// Now foo is no longer valid.
}
Run Code Online (Sandbox Code Playgroud)
至于返回自动释放的对象,这是自动释放的主要用例之一.你正在返回一个将很快消失的对象,但如果调用者感兴趣,他可以保留并接管所有权.(就像你赦免图像一样,用燃烧的安全保险丝传递炸弹.如果来电者有兴趣,他会通过保留来放出保险丝.)如果来电者不感兴趣,可能他会忽略输出从一个函数或只是使用该值来构造一些其他对象,他没有做任何事情,对象将失去内存:
- (id) createObject {
return [NSString stringWith…];
}
- (void) interestedCaller {
NSString *value = [[self createObject] retain];
}
- (void) notInterestedCaller {
[self createObject]; // maybe just interested in side effects
NSString *differentString = [NSString stringWithString:[self createObject]];
}
Run Code Online (Sandbox Code Playgroud)
这非常方便,使手动内存管理非常愉快.您可能对运行循环和Scott Stevenson的Objective-C教程感兴趣.
小智 8
严格来说,
- (void)printHello {
NSString *string;
string = [NSString stringWithFormat:@"Hello"];
NSLog(@"%@", string);
}
Run Code Online (Sandbox Code Playgroud)
不等于
- (void)printHello {
NSString *string;
string = [[[NSString stringWithFormat:@"Hello"] retain] autorelease];
NSLog(@"%@", string);
}
Run Code Online (Sandbox Code Playgroud)
惯例是一个方法应该自动释放它返回的任何对象.唯一的例外(AFAIK)是构造函数,它返回一个具有+1保留计数的对象.因为[NSString stringWithFormat:]返回一个对象.在第一个片段中,stringWithFormat:返回已经自动释放的对象.第二个片段,你再次保留它,它将被释放两次(具有相同的效果,但第二个保留/自动释放对是多余的).
好的,现在回答你的问题.基本上,每次UIKit调用您的代码时,它都会创建一个NSAutoreleasePool对象.每次自动释放对象时,都会将其添加到此池中.最后,当您的代码返回到UIKit时,它会调用池上的drain方法(即[pool drain])并释放已添加到池中的每个对象并释放池.此外,自动释放池可以嵌套,因此如果您要创建大量自动释放的对象,则可以创建自己的池并将其耗尽.它并不像听起来那么复杂.
我强烈建议您阅读" 内存管理指南"中的" 自动释放池"章节(顺便提一下,就在" 实用内存管理"一章之后).
| 归档时间: |
|
| 查看次数: |
3450 次 |
| 最近记录: |