如果我在全局范围的类文件中声明一个静态对象句柄。分配给此句柄的对象是自动释放的对象。然后,在我的应用程序生命周期中,此对象将在内存中保留多长时间?
答案 0 :(得分:5)
如果我在全局范围的类文件中声明一个静态对象句柄。分配给此句柄的对象是自动释放的对象。然后,在我的应用程序生命周期中,此对象将在内存中保留多长时间?
简答:您希望您的全局成为强大的参考。在MRC中,您必须为全局变量添加保留和释放。在ARC中,全局隐含强大(ARC为您添加它们)。
长答案: 在ARC下,您的静态全局变量是一个强引用。在MRC中,您将在设置时保留此变量,然后释放上一个对象。如果你没有,那么你可以在它被取消分配后(悬挂指针)访问它。
因为它是一个强引用,所以你的对象将保持有效,直到a)全局变量的强引用被放弃,b)自动释放池被排出c),当然任何其他强引用都被放弃了。< / p>
因此,如果您对该全局使用强引用并且永远不会重新分配它(逻辑上,放弃全局的强引用),那么您的对象永远不会被dealloc
'编辑。
当您使用不安全的非重定义语义(通过ARC中的装饰,或MRC中的static
的默认值)时,在当前自动释放池耗尽并且所有强引用时,对象将为-dealloc
被删除。这是用程序(MRC)最简单的说明;
static MONObject * GlobalObject;
//
// In MRC, you must add the reference counting to ensure you do not end up with a dangling
// pointer, so false is what how your program should be written in MRC.
//
// In ARC, your program will look like NonRetainedOwnership because it treats the global
// as a strong reference.
static const bool NonRetainedOwnership = ...T/F...;
...
// assume GlobalObject is accessed from one thread only -- i won't bother with
// the supporting code to illustrate how this should be made thread safe.
- (MONObject *)sharedObject
{
if (nil == GlobalObject) {
if (NonRetainedOwnership) {
// don't do this! lifetime will be determined by strong client references
// and the reference you rely on now will be lost when the thread's current
// autorelease pool is drained -- leaving you with a dangling pointer which
// will cause issues when -sharedObject is called again.
GlobalObject = [[MONObject new] autorelease];
}
else {
// Good - keep a strong reference:
GlobalObject = [MONObject new];
}
}
return GlobalObject;
}
- (void)disposeSharedObject
{
if (NonRetainedOwnership) {
GlobalObject = nil;
}
else {
// remove our reference, which was established at [MONObject new]
// assuming there are no strong external references, the object
// will be dealloc'ed -- but you should not make that assumption
// if you return it.
[GlobalObject release], GlobalObject = nil;
}
}
因此,如果NonRetainedOwnership为true并且您使用的是MRC,那么您的对象通常会在-dealloc
返回后不久-sharedObject
- 假设无论谁调用-sharedObject
都没有强引用。在这种情况下,“很快”意味着池通常会在当前的callstack中耗尽几帧,当你在主线程上时通常在AppKit或UIKit中,因为我没有看到很多人在主要线程上显式创建自动释放池线。 borrrden在“1/60秒”之后说,假设在主线程的运行循环中创建并自动释放对象(如果我错了,请纠正我)。 'Kits在主运行循环的每次迭代中创建自动释放池,但是您的程序可能在辅助线程上运行,或者可能存在内部自动释放池,因此生命周期可能更短或更长。通常情况下,你不需要深入思考这些事情 - 只需在这里使用强引用,因为你真的没有办法确保这个全局变量正确发生。
如果您只是简单地写了:@autoreleasepool{[[MONObject new] autorelease];} NSLog("Hi");
那么该对象将(在正常情况下)在NSLog被调用时被释放。
答案 1 :(得分:1)
变量的声明并不重要,重要的是你什么时候为它分配了一个自动释放的对象,如果它在任何自动释放池下被分配,那么它将耗尽它,否则它将在程序终止时被释放通过main方法中的自动释放池!
变量只是一个指针,除非明确地完成,否则不会保留对象,这就是首选保留静态对象的原因:Why retain a static variable?
答案 2 :(得分:0)
当游泳池“耗尽”时。这可能不会马上发生。 请参阅a similar question
答案 3 :(得分:-2)
这取决于。如果变量只初始化一次,并且应该在应用程序的生命周期内保持不变,那么不应该,它不应该被释放(无论如何,当应用程序退出时,它的内存基本上会被释放)。但是,如果静态变量的值发生变化,则是,当静态变量设置为新对象时,应释放上一个对象。