For instance:
we always write like this way 1:
-(NSObject*)giveMeAnObject
{
return [[[NSObject alloc] init] autorelease];
}
-(void)useObject
{
NSObject *object = [self giveMeAnObject];
//use that object
}
but why don’t we write like this way 2:
-(NSObject*)giveMeAnObject
{
return [[NSObject alloc] init];
}
-(void)useObject
{
NSObject *object = [self giveMeAnObject];
//use that object
[object release];
}
The Cocoa SDK do things like way 1, I think thats why we all use way 1, it has become a coding convention.
But I just think that if the convention is way 2, we can gain little performance improvement.
So is there any other reason that we use way 1 instead way 2 except coding convention?
Returning an autoreleased object is a form of abstraction — a convenience for the developer, so he/she does not have to think about the reference counting of the returned object as much — and consequently results in fewer bugs in specific categories (although you can also say autorelease pools introduce new categories of bugs or complexities). It can really simplify the clients code, although yes, there can be performance penalties. It can also be used as an abstracted optimization when no reference operation must be made – consider when the object holds an instance of what is returned and no retain or copy need be made. Although chaining statements can be overused, this practice is also convenient for chaining statements.
Also, the static analyzer which determines reference count errors is relatively new to some of these libraries and programs. Autorelease pools preceded ARC and static analysis of objc objects’ reference counts by many years — ensuring your reference counting is correct is much simpler now with these tools. They are able to detect many of the bugs.
Of course with ARC, a lot of that changes if you favored the simplicity of returning autoreleased objects — with ARC, you can return fewer autoreleased objects without the chance of introducing the bugs autorelease pools abstracted.
Using uniform ownership semantics also simplifies programs. If an abstract selector or collection of selectors always return using the same semantics, then it can really simplify some generic forms. For example — if a set of selectors passed to
performSelector:had different ownership-on-return semantics, then it would add a lot of complexity. So uniform ownership on return can really simplify some of the more ‘generic’ implementations.Performance: Reference count operations (retain/release) can be rather weighty — especially if you are used to working in lower levels. However, the current autorelease pool implementations are very fast. They have been recently updated, and are faster than they used to be. The compiler and runtime use several special shortcuts to keep these costs low. It’s also a good idea to keep your autorelease pool sizes down — particularly on mobile devices. Creating an autorelease pool is very fast. In practice, you may see from zero to a few percent increase from the autorelease operations themselves (i.e. it consumes much less time than
objc_msgSend+variants). Some tests even ran slightly faster. This isn’t an optimization many people will gain much from. It wouldn’t qualify as low hanging fruit under typical circumstances, and it’s actually relatively difficult to measure the effects and locality of such changes in real programs — based off some testing I did after bbum mentioned the changes below. So the tests were limited in scope, but it appears to be better/faster in MRC and ARC.So a lot of this comes down to the level of responsibility you want to assume, in the event you are performing your own reference counting operations. For most people, it shouldn’t really change how they write. I think localizing memory issues, more deterministic object destruction, and more predictable heap sizes are the primary reasons one might favor return an ‘owning’ (+1) reference count if you are running on modern systems. Even then, the runtime and compiler work to reduce this for you in many cases (see bbum’s answer +1). Even though autorelease pools are approximately as fast, I don’t intend on using them more than I do now at this time — so there are still justifiable reasons to minimize using them, but the reasons are lessening.