Another "Retain, then Release" question
being a Cocoa/Obj-C newbie I am going through the "Cocoa Programming for Mac OS X" book by Aaron Hillegass and - leaving apart the fact that now we have also the chance to use GC to avoid all this reasoning - I am not sure I get the reason for some of those retains.
In particular in one of the examples Aaron gives as good programming practice:
- (void) setFoo:(NSCalendarDate *)x
{
[x retain];
[foo release];
foo = x;
}
I don't get the reason for retaining the x instance at the first line of the method:
[x retain];
The scope of开发者_如何学Python this instance is just the set method, right? When exiting the method scope the x instance should be deallocated anyway no? Besides, when assigning x to foo with:
foo = x;
foo will be anyway pointing to x memory cells and will therefore increment the pointed object retain count, no? This should ensure the memory won't be deallocated.
So, what's the point? I am sure I am missing something, of course, but don't know what exactly.
Thanks, Fabrizio
Retain means: I will be needing this object to stay around, it must not be deallocated. If x
wouldn't be retained, the following is likely to happen:
You assign x
to foo
, so foo
now points to the address where your NSCalendarDate is. Someone releases or autoreleases this object, it's retain count eventually drops to 0 and the object is deallocated. Now your foo
still points to that address, but there's no longer a valid object. Sometime later, a new object is created and by chance it's situated at the same address than your old NSCalendarDate object. Now your foo
points to an entirely different object !
To prevent that, you need to retain
it. You need to say, please do not deallocate the object yet, I need it. Once you're done with it, you release
it which means I no longer need the object, you can clean it up now if nobody else needs it.
Now for the classical three part assignment. Consider your setFoo:
would look like this:
- (void) setFoo:(NSCalendarDate *)x
{
[foo release];
[x retain];
foo = x;
}
This is a very bad idea. Consider your object is the only one who has retained the NSCalendarDate object, and consider you would then do: [self setFoo:foo];
. Might sound silly, but something like this can happen. The flow would now be this:
foo
would be released. Its retain count might now drop to 0 and the object will get deallocated.- Whoops, we're trying to retain and access a deallocated object.
This is why you always first retain
the new object, then release
the old object.
If you're coming from a Java or .NET background, it is very important to understand that a variable of type Foo *
only contains the address of your object, nothing more. In Java or .NET, a variable that points to an object automatically "retains" it, if you will. Not so in Objective-C (in non-GC environments). You could consider a variable of type Foo *
to be a weak reference, and you explicitly need to tell Objective-C whether you will still need that object at that address or not.
精彩评论