这是一个使用ARC的OS X的Objective-C程序 - 您可以使用cc -fobjc-arc -o objc_arc_test objc_arc_test.m
或其他东西构建它。它创建了两对两个对象,一个使用alloc / init,另一个使用工厂函数(你在预先ARC代码中使用autorelease
的那种东西),所有这些都在任何自动释放池之外,打印init和dealloc消息。
#import <Foundation/NSObject.h>
#include <stdio.h>
#if !__has_feature(objc_arc)
#error
#endif
@interface TestClass:NSObject {
int value;
}
-(TestClass *)initWithValue:(int)value;
-(void)dealloc;
+(TestClass *)testClassWithValue:(int)value;
@end
@implementation TestClass
-(TestClass *)initWithValue:(int)value_ {
if((self=[super init]))
self->value=value_;
printf("init: self=%p value=%d\n",self,self->value);
return self;
}
-(void)dealloc {
printf("dealloc: self=%p value=%d\n",self,self->value);
}
+(TestClass *)testClassWithValue:(int)value {
return [[TestClass alloc] initWithValue:value];
}
@end
static void f() {
TestClass *c5=[TestClass testClassWithValue:5];
TestClass *c6=[[TestClass alloc] initWithValue:6];
}
static void f2() {
TestClass *c7=[TestClass testClassWithValue:7];
TestClass *c8=[[TestClass alloc] initWithValue:8];
}
int main() {
f();
f2();
}
我希望获得4个对象的初始化消息,以及2个dealloc消息,因为ARC将确保销毁alloc + init对象,并且由于缺少自动释放池,留下其他人。
但我得到的是4个对象的初始化消息,以及3个的dealloc消息:
init: self=0x7fea20500690 value=5
init: self=0x7fea205006f0 value=6
dealloc: self=0x7fea205006f0 value=6
init: self=0x7fea205006f0 value=7
init: self=0x7fea20500700 value=8
dealloc: self=0x7fea20500700 value=8
dealloc: self=0x7fea205006f0 value=7
我不明白这种行为!我希望value = 5和value = 7个对象的行为相同。
为什么要这样做?
(OS X 10.11.6; Xcode 8 - Apple LLVM version 8.0.0 (clang-800.0.38)
,Target: x86_64-apple-darwin15.6.0
,Thread model: posix
)
答案 0 :(得分:4)
因为我相信OS X 10.9,所以即使你没有自己创建一个自动释放池,也可以自动创建一个自动释放池(这摆脱了历史性的#34;没有自动释放池的自动释放对象,只是泄漏&#34;警告)。
那就是说,这与这种情况并不特别相关。 ARC并不承诺任何事情都会被自动释放。当它可以证明您以后不会使用该对象时,它可以自由使用显式版本。 ARC只有义务确保不破坏具有强引用的对象,并且销毁没有强引用的对象。 Autoreleasepool是ARC可以自由使用或不自行决定使用的实现细节。作为优化,ARC通常会避免在我们过去手动使用它的地方使用自动释放池。
值得注意的是,dealloc
实际上从未得到承诺。程序可以在不运行的情况下自由终止(这是一个巨大的优化,这就是ObjC程序可以比C ++程序更快地终止的原因)。在这种情况下,它会发生,但如果您依赖dealloc
运行或未运行,则可能会误用它。