but the purpose of this question is to understand Objective-C
reference counting
You are going to understand less of Cocoa memory management if you use vector
rather than using NSArray
. This is because methods that follow Cocoa memory management rules cooperate together in a nice way; but the methods of vector
are not written with retains and releases, and so do not follow Cocoa manual reference counting rules. So unless you're using ARC, you're going to have to break memory management rules yourself to explicitly memory-manage it from the outside. This is terrible and will teach you wrong ideas.
The great thing about Cocoa memory management is that it is completely local. You retain and release only based on what you do in the function, and you never have to worry about what other functions do. That's what makes it possible to statically analyze memory management and implement ARC.
What do I mean? The basic rule of Cocoa memory management is that object arguments of a function are guaranteed to be valid (i.e. not deallocated) when a function is called, and there is no guarantee about it being valid any time after. That's it. So when you pass an argument to another function, as long as the object is valid when you pass it, that's all you need to worry about. You never need to "retain the object for the other function" because the other function cannot assume that the object is valid at any time after anyway.
This includes adding things to an NSArray
:
Foo *obj = [[Foo alloc] init];
[myArray addObject:obj];
[obj release];
Since you no longer need obj
after adding it, you are free to release it. You don't need to worry about anything else. Now, as other people said, this works because the array retains its elements. But you don't need to know that. NSArray methods follow the same rules as all other methods of objects. You don't need to know how NSArray or any other class works to do memory management right. You don't even need to know what type of object is myArray
or what addObject:
does. That method takes care of it -- if it needs to keep the object around for longer, it must (as part of the memory management rules) somehow retain it; if it does not need to keep it, it doesn't need to do anything. The point is, it doesn't matter to you.
Another example:
Foo *obj = [[Foo alloc] init];
[someObj performSelector:@selector(something:) withObject:obj afterDelay:5];
[obj release];
This does something asynchronous, so how can we release it? Won't it be invalid by the time it is used? No. Again, this all follows the same memory management rules. You don't need to worry about what that method does. If it needs to keep the object around somehow (and it does in this case), it must retain it (and it indeed does) and take care of releasing it, etc.
All this simplicity and beauty goes away if you try to force something like vector
into the picture. You will have to retain things before putting them in, and release things every time an element is removed. It is terrible. You could write a wrapper class around vector so you can have all the terrible memory management logic in that file and others can use it as a normal Objective-C class; but then that would be pretty much like NSMutableArray
.