之间的区别是什么下面的2种方式分配和init一对象?

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

self.aController= [[AController alloc] init];

大多数的苹果如使用第一种方法。为什么你会分配,init和目的,然后立即释放?

有帮助吗?

解决方案

每个对象都有引用计数。当它变为0时,该对象被解除分配。

假设该属性声明为 @property(retain)

你的第一个例子,一行一行:

  1. 该对象由 alloc 创建,其引用计数为1.
  2. 该对象被移交给 self setAController:方法,该方法向其发送 retain 消息(因为该方法不知道对象来自哪里),将其引用计数增加到2。
  3. 调用代码不再需要对象本身,因此它调用 release ,将引用计数递减为1.
  4. 你的第二个例子基本上是第1步和第2步,但不是3,所以最后对象的引用数是2。

    规则是如果你创建了一个对象,那么当你完成它时,你有责任释放它。在您的示例中,代码在设置属性后使用tempAController完成。如果需要该对象的话,调用 retain 是setter方法的责任。

    重要的是要记住,Objective-C中的 self.property = foo; 实际上只是 [self setProperty:foo]; 的简写,而 setProperty:方法将根据需要保留或复制对象。

    如果属性声明为 @property(copy),则该对象将被复制而不是保留。在第一个例子中,原始对象将立即释放;在第二个例子中,原始对象的引用计数将为1,即使它应该为0.所以你仍然希望以相同的方式编写代码。

    如果属性声明为 @property(assign),则 self 不声明对象的所有权,而其他人需要保留它。在这种情况下,第一个例子是不正确的。这些属性很少见,通常只用于对象委托。

其他提示

如其他人已经指出的,这两段代码显示你不是同等的(对于存管理的原因)。为什么前者是选择了后者:

将制定正确的后一会

self.aController= [[[AController alloc] init] autorelease];

与前者相比,这增加了额外的开销,通过利用自动释放游泳池,并在某些情况下会导致对象的生命周期被不必要地延长(直至自动释放游泳池被释放),这将提高应用程序的存储排放。

其它的"可能的"实施(取决于其中的例子是由)是简单:

aController = [[AController alloc] init];

然而,设置的一个实例可变直接强烈劝阻任何地方比在其他init或dealloc方法。在其他地方应始终使用存取的方法。

这给我们带来了然后执行表示在试样的代码:

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

这下最佳做法,因为:

  • 它避免了自动释放;
  • 它使得存储管理语义不清楚;
  • 它使用一个访问方法来设置的实例可变的。

另请注意,您希望将代码缩减为一行,这是许多人使用Autorelease的原因:

self.aController = [[[AController alloc] init] autorelease];

虽然理论上关于iPhone的自动释放在某种程度上更加昂贵(从未听说过明确的原因),因此您可能希望在将对象分配到其他地方后立即发布。

如果您正在使用Xcode,它可以帮助您使用静态分析器检测此类代码。 只需按Build>>建立和分析

这将在这些代码中向您显示一条非常有用的信息。

另外需要注意的是,您的示例还取决于aController的@property定义。

如果它被定义为 @property(readwrite,retain)id aController; 那么你的例子可以工作,而如果它被定义为 @property(readwrite,assign)id aController; 然后对release的额外调用会导致你的对象被释放。

您也可以

@property (nonatomic, retain)AController *aController;
...
self.aController= [[AController alloc] init];
[aController release];

带有保留属性,它的功能相同,但最好使用另一种方式(保留属性),因为它不那么混乱,代码使它看起来像你分配一个控制器然后从内存中删除,实际上它不是因为setAController保留它。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top