假设,A类的以下声明
@property(nonatomic, assign) DoublyLinkedList *doublyLinkedList;
,作为init的一部分,初始化了对象
- (id)init {
self = [super init];
if (self) {
doublyLinkedList = [[DoublyLinkedList alloc] init];
}
return self;
}
那个方法
- (DoublyLinkedList*) doSomethingAndReturn {
最终
return doublyLinkedList;
A类在返回后是否拥有doublyLinkedList
?
答案 0 :(得分:2)
编辑:init
添加了alloc
您没有在其上调用retain
,但在init
中您正在调用alloc
,因此它的保留计数为1 - 您拥有它并且您应该在dealloc
中发布。
您可以简单地alloc
并在dealloc
中发布它。酒店的来电者可以选择是否保留。另一种选择是在init
中创建对象,自动释放它,然后使用(retain)
而不是(assign)
将其分配给属性。这样,如果代码alloc
中的其他位置并分配给该属性,则alloc
'对象将被释放。然后在dealloc
中,它当前分配的内容将被释放。
如果您不希望其他人设置,则另一种选择是拥有(readonly)
属性和_doubleLinkedList
iVar,然后@synthesize doublyLinkedList = _doubleLinkedList
。然后,您可以在init
中分配一次,并知道没有其他人会分配它,然后在dealloc
中发布它。
一个很好的类比是,当你保留时,你会对它施加牵引力。多个项目可以在该对象上放置皮带。只有当每个人都脱掉皮带时,它才会被释放。
阅读的好指南:
Apple's Memory Management Programming Guide
特别是从该文档中,这些规则有助于:
您拥有自己创建的任何对象您可以使用方法创建对象 其名称以“alloc”,“new”,“copy”或“mutableCopy”开头(for 例如,alloc,newObject或mutableCopy)。
您可以使用保留获取对象获取对象的所有权 通常保证在它的方法中保持有效 收到,并且该方法也可以安全地将对象返回到它 调用。您在两种情况下使用retain:(1)在实现中 访问方法或init方法,以取得一个 要作为属性值存储的对象; (2)防止 对象被作为其他一些操作的副作用而无效 (如“避免导致重新分配对象”中所述 使用”)。
当你不再需要它时,你必须放弃一个人的所有权 您拥有的对象您通过发送对象放弃对象的所有权 发布消息或自动释放消息。在Cocoa术语中, 因此,通常会提到放弃对象的所有权 作为“释放”一个对象。
您不得放弃您不拥有的对象的所有权这 只是明确说明以前的政策规则的必然结果。
答案 1 :(得分:1)
对象并非以这种方式“拥有”。当保留计数为0时,Objective-C将释放对象的内存。如果A类的实例处于活动状态,则A类依赖于doubleLinkedList“保持活动”,则对象A保留doublyLinkedList以增加该保留如上所述,当对象A返回对doublyLinkedList的引用时,接收该结果的调用者也可以选择保留该对象,这会使保留计数再次增加1。
所以尽量不要把它想象成拥有一个对象。相反,将其视为表达对对象存在的兴趣。只要有人继续对该对象感兴趣,如其保留计数所表示的那样,那么该对象将不会被释放。
答案 2 :(得分:1)
正如您所定义的那样,A类从未保留过doublyLinkedList。所以不,它没有任何利害关系。实际上,因为类A不保留doublyLinkedList,所以可以在执行期间随时解除分配并导致EXEC_BAD_ACCESS崩溃。
有两种明显的方法可以解决这个问题。
编辑:
如果在初始化A类时对alloc-init对象进行初始化,就像上面添加的那样,那么只应在释放A类时释放该对象。这使得对象生命周期变得简单。创建一个A类实例,它创建一个DLL对象。该对象一直存在,直到A类实例被销毁。如果其他对象想要使用DLL,他们只需从A类实例请求它,并保留它。
保留版本的目标是以这样的方式编写代码,以确保您拥有偶数的保留调用,并释放对象的调用。对于每一个:
- (id)init {
self = [super init];
if (self) {
doublyLinkedList = [[DoublyLinkedList alloc] init];
}
return self;
}
你需要一个:
-(void)dealloc {
[super dealloc];
[doublyLinkedList release]
}
如果您的类对象要创建和处理多个DLL对象,则不要在-(id)init
中创建它并使用retain
作为属性声明。
然后:
ClassA *newClassAObject = [[ClassA alloc] init]; // create class a object
newClassAObject.doublyLinkedList = [[[DoublyLinkedList alloc] init] autorelease]; // make a DLL object, only retained by class a object.
DoublyLinkedList *dll = [newClassAObject doSomethingAndReturn]; // process the list somehow
[dll retain] // we own this now
newClassAObject.doublyLinkedList = nil; // class A object gives up interest in dll.
newClassAObject.doublyLinkedList = [[[DoublyLinkedList alloc] init] autorelease]; // now process another one.
... and on and on ...