Releasing an object can free up its memory, which can be a concern if you're creating many objects during the execution of a program. A good rule is to release objects you've created or retained when you're done with them.
Sending a release message does not necessarily destroy an object. When an object's reference count is decremented to 0, the object is destroyed. The system does this by sending the dealloc message to the object to free its memory.
The autorelease pool provides for the automatic release of objects when the pool itself is released. The system does this by sending a release message to each object in the pool for each time it was autoreleased. Each object in the autorelease pool whose reference count goes down to 0 is sent a dealloc message to destroy the object.
If you no longer need an object fro within a method but need to return it, send it an autorelease message to mark it for later release. The autorelease message does not affect the reference count of the object. So, it enables the object to be used by the message sender but still be freed up later when the autorelease pool is released.
When your application terminates, all the memory taken by your objects is released, whether or not they were in the autorelease pool.
When you develop more sophisticated applications (such as Cocoa applications), autorelease pools can be created and destroyed during execution of the program (for Cocoa applications, that happens each time an event occurs). In such cases, if you want to ensure that your object survives automatic deallocation when the autorelease pool itself is released, you need to explicitly retain it. All objects that have a reference count greater than the number of autorelease messages they have been sent will survive the release of the pool.
If you directly create an object using an alloc or copy method (or with an allocWithZone:, copyWithZone:, or mutableCopy method), you are responsible for releasing it. For each time you retain an object, you should release or autorelease that object.
You don't have to worry about releasing objects that are returned by methods other than those noted in the previous rule. It's not your responsibility; those objects should have been autoreleased by those methods. That's why you needed to create the autorelease pool in your program in the first place. Methods such as stringWithString: automatically add newly created string objects to the pool by sending them autorelease messages. If you don't have a pool set up, you get a message that you tried to autorelease an object without having a pool in place.