开发者

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:

  1. foo would be released. Its retain count might now drop to 0 and the object will get deallocated.
  2. 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.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜