NSNumber* n = [[NSNumber alloc] initWithInt:100];
NSNumber* n1 = n;
In the code above, why is the value of n\'s retainCount set to 2? In the second
I think you have something else going on...
NSNumber* n = [[NSNumber alloc] initWithInt:100];
NSNumber* n1 = n;
NSLog(@"n = %i",[n retainCount]);
Result is 1
Retain counts are an implementation detail. They can be kindasorta useful in debugging, sometimes, but in general you should not care about them. All you should care about is that you're following the memory management rules.
For an example of why looking at retain counts is unreliable, this is a perfectly legal class that obeys the API contract and will behave correctly in all circumstances:
@implementation CrazyClass
- (id)retain {
for(int i=0; i<100; i++) {
[super retain];
}
}
- (void)release {
for(int i=0; i<100; i++) {
[super release];
}
}
@end
…but if you inspected its retain count, you'd think you had an "issue."
This precise case doesn't happen too often in practice, but it illustrates why looking at retain counts is useless for telling if something is wrong. Objects do get retained behind the scenes by code outside of your control. NSNumber, for example, will sometimes cache instances. Objects get autoreleased, which isn't reflected in the retain count. Lots of things can happen that will confuse the retain count. Some classes might not even keep their retain counts where you can see them.
If you suspect you have a leak, you should check with the real debugging tools meant for that purpose, not by poking at retain counts. And for code you're writing, you should primarily be concerned with following the guidelines I linked above.
Stop. Just stop. Never look at the retainCount
of an object. Ever. It should never have been API and available. You're asking for pain.
There's too much going on for retainCount
to be meaningful.
You should never rely on the retainCount
of an object. You should only use it as a debugging aid, never for normal control flow.
Why? Because it doesn't take into account autorelease
s. If an object is retain
ed and subequently autorelease
d, its retainCount
will increment, but as far as you're concerned, its real retain count hasn't been changed. The only way to get an object's real retain count is to also count how many times it's been added to any of the autorelease pools in the autorelease pool chain, and trying to do so is asking for trouble.
In this case, the retainCount
is 2 because somewhere inside alloc
or initWithInt:
, the object is being retain
ed and autorelease
d. But you shouldn't need to know or care about that, it's an implementation detail.
Based on this link here, it's possible that there's some optimization going on under the covers for common NSNumbers (which may not happen in all implementations hence a possible reason why @dizy's retainCount is 1).
Basically, because NSNumbers are non-mutable, the underlying code is free to give you a second copy of the same number which would explain why the retain count is two.
What is the address of n and n1? I suspect they're the same.
NSNumber* n = [[NSNumber alloc] initWithInt:100];
NSLog(@"Count of n : %i",[n retainCount]);
NSNumber* n1 = n;
NSLog(@"Count of n : %i",[n retainCount]);
NSLog(@"Count of n1: %i",[n1 retainCount]);
NSLog(@"Address of n : %p", n);
NSLog(@"Address of n1: %p", n1);
Based on your update, that link I gave you is almost certainly the issue. Someone ran a test and found out that the NSNumbers from 0 to 12 will give you duplicates of those already created (they may in fact be created by the framework even before a user requests them). Others above 12 seemed to give a retain count of 1. Quoting:
From the little bit of examination I've been able to do, it looks as if you will get "shared" versions of integer NSNumbers for values in the range [0-12]. Anything larger than 12 gets you a unique instance even if the values are equal. Why twelve? No clue. I don't even know if that's a hard number or circumstantial.
Try it with 11, 12 and 13 - I think you'll find 13 is the first to give you a non-shared NSNumber.