Why does NSSet objectEnumerator increase the hold count?

After getting the Enumerator object in the following code, the set1 counter will be 3. I was surprised to see this because I didn't expect it to change. I searched the documentation and couldn't find where this effect is explained.

My guess is that additional holds are probably set to autorelease by Cocoa's enumeration logic and won't actually have any effect in the current event loop. Surely the objectEnumerator logic needs a reference to set1, but I would like to know why they were made. Here's why: if I assume that set1 will retain a null value after being released in code, I could try to reuse it with another new set. Wouldn't that cause a problem since set1 is now pointing to a completely different object / address?

Regarding "bonus" points, is there a way to list the auto resource pool to see what it actually contains? TIA

#import <Foundation/NSObject.h>
#import <Foundation/NSSet.h>
#import <Foundation/NSValue.h>
#import <Foundation/NSEnumerator.h>
#import <Foundation/NSAutoreleasePool.h>
#import <Foundation/NSString.h>

#import <stdio.h>;

// macro to create an integer number:
#define INTOBJ(v) [NSNumber numberWithInt: v]

int main (int argc, char *argv[])
    NSAutoreleasePool *pool = [NSAutoreleasePool new];

    //Make set
    NSMutableSet *set1 = [[NSMutableSet alloc] initWithObjects:
        INTOBJ(1), INTOBJ(2), INTOBJ(5), INTOBJ(10), nil];

    printf("set1 #%lu\n", [set1 retainCount]);

    //Get enumerator of the set. This is where the retain count goes to 3:
    NSEnumerator *setEnum = [set1 objectEnumerator];
    printf("setEnum #%lu\n", [setEnum retainCount]);
    printf("set1 #%lu\n", [set1 retainCount]);

    //Iterate through the collection:

    NSNumber *element;
    while ((element = [setEnum nextObject]) != nil)
        //do some this with item. printf is just for debugging:
        printf(" %i ", [element intValue]);

    printf("set1 #%lu\n", [set1 retainCount]);

    [set1 release];
    printf("set1 after release #%lu\n", [set1 retainCount]);

    //More logic could go here reusing variable set1 since I assumed retain count = 0

    [pool release];

    return 0;



source to share

3 answers

Generally, you shouldn't rely on the object storage counter, as it is an internal detail of the structure. Instead, make sure your code adheres to memory management principles, specifically to balance save / new / copy and release / auto-advertisements.



Presumably the enumerator keeps the collection so that it doesn't get freed during enumeration. An enumerator without a valid collection to enumerate won't work very well. In fact, the only way for an enumerator to make sure that it will work is to store the list it is listing.

However, there really is no reason to ever look at the hold count of any object other than debugging a memory leak / double release issue. As long as you follow memory management conventions, you never have to worry about holding an object.



Reusing set1 after release will not cause problems, since the save counter is in the object referenced by set1, not the variable itself.



All Articles