Objective C中的对象分配和初始化

Ron*_*iew 56 cocoa cocoa-touch memory-management objective-c

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

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];
Run Code Online (Sandbox Code Playgroud)

self.aController= [[AController alloc] init];
Run Code Online (Sandbox Code Playgroud)

大多数苹果示例使用第一种方法.为什么要分配,初始化和对象然后立即释放?

ben*_*ado 70

每个对象都有一个引用计数.当它变为0时,对象被释放.

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

你的第一个例子,逐行:

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

您的第二个示例基本上执行步骤1和2但不执行步骤3,因此最后对象的引用计数为2.

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

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

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

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


mma*_*alc 31

正如其他人所说,你展示的两个代码片段并不相同(出于内存管理的原因).至于为何选择前者而不是后者:

后者的正确表述将是

self.aController= [[[AController alloc] init] autorelease];
Run Code Online (Sandbox Code Playgroud)

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

另一个"可能的"实现(取决于示例的来源)简单地说:

aController = [[AController alloc] init];
Run Code Online (Sandbox Code Playgroud)

但是,强烈建议不要在init或dealloc方法之外的任何地方直接设置实例变量.在其他地方,您应该始终使用访问器方法.

这将我们带到示例代码中显示的实现:

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];
Run Code Online (Sandbox Code Playgroud)

这符合以下最佳做法:

  • 它避免了自动释放;
  • 它使内存管理语义立即清晰;
  • 它使用访问器方法来设置实例变量.

  • mmalc是对的.但是......实际上,分配给1个变量的3行代码简直就是疯了.我见过的大多数团队使用autorelease"在一行代码中完成所有工作"的方法 - 开销很小.如果你在iPhone上遇到过显着性能差异的情况,你可能应该用C重写那段代码 - 你做的分配太多了.很少有团队会坚持"官方"会议(正确地说,恕我直言 - 现实世界的节目应该是明确的,但不是口头上的腹泻). (10认同)

Ken*_*ner 5

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

self.aController = [[[AController alloc] init] autorelease];
Run Code Online (Sandbox Code Playgroud)

虽然从理论上讲,iPhone自动释放在某种程度上更加昂贵(从未听说过明确的解释原因),因此您可能希望在将对象分配到其他位置后立即显式释放.


lev*_*han 5

如果您正在使用Xcode,它可以帮助您使用静态分析器检测此类代码.点击Build >> Build and Analyze

替代文字

这将在这些代码片段中向您显示一条非常有用的消息.

替代文字