目标C中的对象分配和初始化

以下两种分配和初始化对象的方式有什么区别?

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

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

大多数的苹果例子使用第一种方法。 为什么要分配init和object,然后立即释放?

每个对象都有一个引用计数。 当它到0时,对象被释放。

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

你的第一个例子,逐行:

  1. 该对象由alloc创build,它的引用计数为1。
  2. 该对象被交给selfsetAController:方法,该方法发送一个retain消息(因为该方法不知道对象来自哪里),将其引用计数递增为2。
  3. 调用代码不再需要该对象本身,因此它调用release ,将引用计数递减为1。

你的第二个例子基本上做的第一步和第二步,但不是3,所以最后对象的引用计数是2。

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

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

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

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

正如其他人已经指出,你展示的两个代码片段是不相同的(由于内存pipe理的原因)。 至于为什么select前者:

后者的正确表述是

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

与前者相比,这增加了额外的开销,通过使用autorelease池,并在某些情况下会导致对象的生命周期不必要的扩展(直到autorelease池被释放),这将增加您的应用程序的内存足迹。

其他“可能的”实现(取决于示例的来源)只是简单的:

 aController = [[AController alloc] init]; 

但是,直接设置一个实例variables,除了在init或dealloc方法之外,其他任何地方都不鼓励。 在其他地方,你应该总是使用访问器方法。

这使我们看到示例代码中显示的实现:

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

这是遵循最佳做法,因为:

  • 它避免了autorelease;
  • 它使内存pipe理语义立即清晰;
  • 它使用访问器方法来设置实例variables。

还要注意,将代码缩减到一行的愿望是为什么许多人使用Autorelease:

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

虽然在理论上iPhone的autorelease在某种程度上更昂贵(从来没有听清楚的解释,为什么),因此你可能希望明确释放后,你分配对象的其他地方。

如果您使用的是Xcode,它可以帮助您使用静态分析器来检测这些代码。 只需点击Build >> Build and Analyze

替代文字

这会在这样的代码中向你显示非常有用的信息。

替代文字

另外要注意的是,你的例子也依赖于aController的@property定义。

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

你也可以做

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

有一个保留的属性,它会以同样的方式工作,但它更好地使用其他方式(保留属性),因为它不那么混乱,代码使它看起来像你分配一个控制器,然后从内存中删除,实际上它不会因为setAController保留它。

Interesting Posts