objective-c Objective C 中的对象分配和初始化
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/156243/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Object allocate and init in Objective C
提问by Ronnie Liew
What is the difference between the following 2 ways to allocate and init an object?
以下两种分配和初始化对象的方式有什么区别?
AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];
and
和
self.aController= [[AController alloc] init];
Most of the apple example use the first method. Why would you allocate, init and object and then release immediately?
大多数苹果示例使用第一种方法。为什么要分配、初始化和对象然后立即释放?
回答by benzado
Every object has a reference count. When it goes to 0, the object is deallocated.
每个对象都有一个引用计数。当它变为 0 时,对象被释放。
Assuming the property was declared as @property (retain):
假设该财产被声明为@property (retain):
Your first example, line by line:
您的第一个示例,逐行:
- The object is created by
alloc, it has a reference count of 1. - The object is handed over to
self'ssetAController:method, which sends it aretainmessage (because the method doesn't know where the object is coming from), incrementing its reference count to 2. - The calling code no longer needs the object itself, so it calls
release, decrementing the reference count to 1.
- 该对象由
alloc,它的引用计数为 1。 - 该对象被移交给
self的setAController:方法,该方法向它发送一条retain消息(因为该方法不知道该对象来自何处),将其引用计数增加到 2。 - 调用代码不再需要对象本身,因此它调用
release,将引用计数递减为 1。
Your second example basically does steps 1 and 2 but not 3, so at the end the object's reference count is 2.
您的第二个示例基本上执行第 1 步和第 2 步,但没有执行第 3 步,因此最后对象的引用计数为 2。
The rule is that if you create an object, you are responsible for releasing it when you're done with it. In your example, the code is done with tempAController after it sets the property. It is the setter method's responsibility to call retainif it needs that object to stick around.
规则是,如果你创建了一个对象,你有责任在完成后释放它。在您的示例中,代码在设置属性后使用 tempAController 完成。retain如果需要该对象保留,则调用 setter 方法是它的责任。
It's important to remember that self.property = foo;in Objective-C is really just shorthand for [self setProperty:foo];and that the setProperty:method is going to be retaining or copying objects as needed.
重要的是要记住,self.property = foo;在 Objective-C 中实际上只是简写,[self setProperty:foo];并且该setProperty:方法将根据需要保留或复制对象。
If the property was declared @property (copy), then the object would have been copied instead of retained. In the first example, the original object would be released right away; in the second example, the original object's reference count would be 1 even though it should be 0. So you would still want to write your code the same way.
如果声明了属性@property (copy),则对象将被复制而不是保留。在第一个示例中,原始对象将立即释放;在第二个示例中,原始对象的引用计数将为 1,即使它应该是 0。因此您仍然希望以相同的方式编写代码。
If the property was declared @property (assign), then selfisn't claiming ownership of the object, and somebody else needs to retain it. In this case, the first example would be incorrect. These sorts of properties are rare, usually only used for object delegates.
如果该属性已声明@property (assign),则self不会声明该对象的所有权,其他人需要保留它。在这种情况下,第一个示例将是不正确的。这些类型的属性很少见,通常仅用于对象委托。
回答by mmalc
As others have noted, the two code snippets you show are not equivalent (for memory management reasons). As to why the former is chosen over the latter:
正如其他人所指出的,您展示的两个代码片段并不等效(出于内存管理原因)。至于为什么选择前者而不是后者:
The correct formulation of the latter would be
后者的正确表述是
self.aController= [[[AController alloc] init] autorelease];
Compared with the former, this adds additional overhead through use of the autorelease pool, and in some circumstances will lead to the lifetime of the object being unnecessarily extended (until the autorelease pool is released) which will increase your application's memory footprint.
与前者相比,这通过使用自动释放池增加了额外的开销,并且在某些情况下会导致对象的生命周期被不必要地延长(直到自动释放池被释放),这将增加应用程序的内存占用。
The other "possible" implementation (depending on where the example is from) is simply:
另一个“可能”的实现(取决于示例的来源)很简单:
aController = [[AController alloc] init];
However, setting an instance variable directly is strongly discouraged anywhere other than in an init or dealloc method. Elsewhere you should always use accessor methods.
但是,强烈建议不要在 init 或 dealloc 方法以外的任何地方直接设置实例变量。在其他地方,您应该始终使用访问器方法。
This brings us then to the implementation shown in sample code:
这将我们带到示例代码中显示的实现:
AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];
This follows best practice since:
这遵循最佳实践,因为:
- It avoids autorelease;
- It makes the memory management semantics immediately clear;
- It uses an accessor method to set the instance variable.
- 它避免了自动释放;
- 它使内存管理语义立即清晰;
- 它使用访问器方法来设置实例变量。
回答by Kendall Helmstetter Gelner
Note also that your desire to cut the code down to one line is why many people use Autorelease:
另请注意,您希望将代码缩减为一行是许多人使用 Autorelease 的原因:
self.aController = [[[AController alloc] init] autorelease];
Though in theory on the iPhone autorelease is somehow more expensive (never heard a clear explanation why) and thus you may want to explicitly release right after you assign the object elsewhere.
尽管理论上 iPhone 自动释放在某种程度上更昂贵(从未听过明确的解释为什么),因此您可能希望在将对象分配到其他地方后立即明确释放。
回答by leviathan
If you're using Xcode, it can help you detect such code with the static analyzer. Just hit Build >> Build and Analyze
如果您使用的是 Xcode,它可以帮助您使用静态分析器检测此类代码。只需点击构建>>构建和分析


This will show you a very helpful message at such pieces of code.
这将在这些代码段中向您显示非常有用的消息。


回答by Ashley Clark
One other thing to note is that your example depends on the @property definition of aController also.
要注意的另一件事是,您的示例还取决于 aController 的 @property 定义。
If it were defined as @property (readwrite, retain) id aController;then your example works, while if it is defined as @property (readwrite, assign) id aController;then the extra call to release would cause your object to be deallocated.
如果它被定义为@property (readwrite, retain) id aController;那么你的例子就可以工作,而如果它被定义为@property (readwrite, assign) id aController;那么额外的 release 调用会导致你的对象被释放。
回答by mk12
You could also do
你也可以这样做
@property (nonatomic, retain)AController *aController;
...
self.aController= [[AController alloc] init];
[aController release];
with a retaining property, and it would function the same way, but its better to use the other way (for retaining properties) because it's less confusing, that code makes it look like you assign aController and then it gets deleted from memory, when actually it doesn't because setAController retains it.
使用保留属性,它会以相同的方式运行,但最好使用另一种方式(用于保留属性),因为它不那么令人困惑,该代码看起来就像您分配了一个控制器,然后它从内存中被删除,实际上它不会因为 setAController 保留它。

