开发者

Object's ownership, after "return". Clarification needed

Assuming, the following declaration for class A

@property(nonatomic, assign) DoublyLinkedList *doublyLinkedList;

, that as part of init, initialized the object

- (id)init {
    self = [super init];
    if (self) {
        doublyLinkedList = [[DoublyLinkedList alloc] init];
    }

    return self;
}

and that a meth开发者_开发百科od

- (DoublyLinkedList*) doSomethingAndReturn {

that ultimately

return doublyLinkedList;

Does class A owns the doublyLinkedList after the return?


EDIT: init added with alloc

You are not calling retain on it, but in init you are calling alloc on it, so it does have a retain count of 1 -- you own it and you should release it in dealloc.

You could simply alloc it and release it in dealloc. The caller of the property can choose whether to retain. Another option would be to create the object in init, autorelease it and then assign it to the property with (retain) instead of (assign). That way, if other places in the code alloc and assign to that property, the object you alloc'd will get released. Then in dealloc, what it's currently assigned to will get released.

Yet another option if you don't want others to set it would be to have a (readonly) property and a _doubleLinkedList iVar and then @synthesize doublyLinkedList = _doubleLinkedList. Then you can allocate it once in init and know that no one else will assign it, and then release it in dealloc.

A good analogy is that when you retain, you're putting a leash on it. Multiple items can put a leash on that object. It is freed only when everyone has taken the leash off.

A good guide to read:

Apple's Memory Management Programming Guide

Specifically from that doc, these rules help:

You own any object you create You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).

You can take ownership of an object using retain A received object is normally guaranteed to remain valid within the method it was received in, and that method may also safely return the object to its invoker. You use retain in two situations: (1) In the implementation of an accessor method or an init method, to take ownership of an object you want to store as a property value; and (2) To prevent an object from being invalidated as a side-effect of some other operation (as explained in “Avoid Causing Deallocation of Objects You’re Using”).

When you no longer need it, you must relinquish ownership of an object you own You relinquish ownership of an object by sending it a release message or an autorelease message. In Cocoa terminology, relinquishing ownership of an object is therefore typically referred to as “releasing” an object.

You must not relinquish ownership of an object you do not own This is just corollary of the previous policy rules, stated explicitly.


Objects aren't really "owned" in that way. Objective-C will free up the memory for an object when its retain count gets to 0. If class A depends on doubleLinkedList being "kept alive" as long as an instance of class A is alive, then object A retains doublyLinkedList to increase that retain count by 1. When object A returns a reference to doublyLinkedList as you have above, then the caller who receives that result may elect to retain the object as well, which would increase the retain count by one again.

So try not to think of it as owning an object. Instead, think of it as expressing an interest in the existence of an object. As long as someone continues to be interested in that object, as expressed by its retain count, then the object will not be deallocated.


As you've defined it, class A has not ever retained doublyLinkedList. So no, it has no stake in it. In fact because doublyLinkedList is not retained by class A, it could be deallocated at any time during execution and cause an EXEC_BAD_ACCESS crash.

There are two obvious ways to deal with this.

  1. Class A should retain doublyLinkedList while it's using it, and autorelease it before it returns it.
  2. Another 'parent' object can retaining both doublyLinkedList and the instance of class A, and it's up to that 'parent' object to make sure doublyLinkedList doesn't get deallocated while the class A object is using it.

Edit:

If you alloc-init the object when you initialize Class A, as you've added above, then you should only release the object when Class A is deallocated. This makes for a simple object life-cycle. An instance of Class A is created, it creates a DLL object. That object persists until the Class A instance is destroyed. If other objects want to use the DLL, they simply request it from the class A instance, and retain it.

The goal with retain release is to code in such a way that you can be sure you have an EVEN number of retain calls, and release calls on an object. For every:

- (id)init {
  self = [super init];
  if (self) {
    doublyLinkedList = [[DoublyLinkedList alloc] init];
  }

  return self;
}

You need a:

-(void)dealloc {
  [super dealloc];
  [doublyLinkedList release]
}

If your class a object is going to be creating and processing more than one DLL object, then don't create it in -(id)init and use retain for the property declaration. then:

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 ...
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜