Re: Numbers and mutable sets and retain counts, oh my!
Re: Numbers and mutable sets and retain counts, oh my!
- Subject: Re: Numbers and mutable sets and retain counts, oh my!
- From: Ken Thomases <email@hidden>
- Date: Sat, 13 Nov 2010 09:56:21 -0600
On Nov 13, 2010, at 8:57 AM, William Squires wrote:
> Let's say I have some sample code that looks like:
>
> -(NSMutableSet *)allOddNumbersExcept5Set
> {
> NSMutableSet *results = [[NSMutableSet alloc] initWithCapacity:1];
>
> for (int i=1; i<=10; i+=2)
> {
> if (i != 5)
> {
> NSString *testNumber = [NSString stringWithFormat:"%d", i];
> // testNumber should now be an autoreleased NSString
> [results addObject:testNumber];
> }
> }
> return results;
> }
You should use NSNumbers to represent numbers as objects.
You are leaking the set. By the naming conventions, a caller of -allOddNumbersExcept5Set does not receive an ownership responsibility. That leaves this method with the responsibility of discharging the ownership responsibility by releasing the set. You'd do that by sending it -autorelease, since you want it to live long enough to reach the caller.
> 1) Do mutable containers (NSMutableArray, NSMutableDictionary, NSMutableSet) always send the 'retain' message to objects added with the 'addObject:' message?
Yes, but you shouldn't care. What you care about is whether your code handles its responsibilities properly. The collection classes are in charge of handling their responsibilities properly, and you should just assume that they do.
It is documented that they extend the life of the contained objects for as long as they are contained.
(And this is irrespective of their mutability.)
> 2) When you retrieve the results from the collection, does the object reference you get back have the same retain count as the one in the container? (i.e. if I add an object to an NSMutableArray (held in an @property) in one method, and retrieve it in another, will I get a retain count of 1 or 2?)
You _really_ don't care about retain counts. Don't pay any attention to them. They will only mislead and confuse you.
Also, this juxtaposition of "the object reference you get back" vs. "the one in the container" is very confused. Object references don't have retain counts. Objects have retain counts. You receive a pointer to the object that is in the container. Since the object you receive a pointer to and the object in the container are one and the same, they have the same retain count.
> 3) Will the above code autorelease the 'testNumber' the second (and third, and fourth...) times through the loop when it gets another autoreleased NSString, or will it just re-use the existing one?
Each time through the loop, you are asking for a different string. Whether that string is autoreleased or not is an open question (it might in fact be a singleton that lives for the life of the process). What is definite is that you do not receive an ownership responsibility and so should not release it (unless you acquire an ownership responsibility by retaining it). You can know this by the memory management rules and the naming conventions.
> 4) Would I be better off with:
>
> -(NSMutableSet *)allOddNumbersExcept5Set
> {
> NSMutableSet *results = [[NSMutableSet alloc] initWithCapacity:1];
>
> for (int i=1; i<=10; i+=2)
> {
> if (i != 5)
> {
> NSString *testNumber = [[NSString alloc] initWithFormat:@"%d", i];
> [results addObject:testNumber];
> [testNumber release];
> }
> }
> return results;
> }
>
> instead?
In this case, you do receive an ownership responsibility for the string (because you called +alloc), and you correctly discharge that responsibility by releasing it. Both this and the previous code were correctly handling the memory management of the string.
This latter technique keeps the object out of the autorelease pool and so is slightly more efficient. The efficiency gain is small enough that it doesn't matter when targeting Mac OS X, but Apple does recommend this approach in the more memory constrained environment of iOS apps.
The former technique is simpler (which counts for a lot), more convenient, and less prone to errors. (For example, if you come back to a piece of code some time later and add in an early return path, it's easy to forget that you need to release the string.)
Regards,
Ken
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden