autorelease is used for returned function object so the caller don't take ownership and callee will release the object in the future.
However, ARC is capable to count ownership of caller and release it after use, that is, it can behavior just like Smart Pointer in C++. With ARC, it can get rid of autorelease because autorelease is non-deterministic.
The reason I ask for this question is that I do see the returned object calls dealloc earlier in ARC than non-ARC code. This leads me to think that ARC can behvior like Smart Pointer and can make autorelease useless. Is it true or possible? The only thing I can think about autorelease usefullness is in multip-thread or network code because it may be not easier to count the ownership when the object is passing around.
Thanks for your thoughts.
Here is new edit to make thing clear:
with autorelease
+ (MyClass*) myClass
{
return [[[MyCClass alloc] init] autorelease];
}
- doSomething
{
MyClass *obj = [MyClass myClass];
}
With ARC:
+ (MyClass*) myClass
{
return [[MyCClass alloc] init]; // no autorelease
}
- doSomething
{
MyClass *obj = [MyClass myClass];
// insert [obj release]
}
So, we really don't need autorelease.
Autorelease as a mechanism is still used by ARC, furthermore ARC compiled-code is designed to interoperate seamlessly with MRC compiled-code so the autorelease machinery is around.
First, don't think in terms of reference counts but in terms of ownership interest - as long as there is a declared ownership interest in an object then the object lives, when there is no ownership interest it is destroyed. In MRC you declare ownership interest by using
retain
, or by creating a new object; and you relinquish ownership interest by usingrelease
.Now when a callee method creates an object and wishes to return it to its caller the callee is going away so it needs to relinquish ownership interest, and so the caller needs to declare its ownership interest or the object may be destroyed. But there is a problem, the callee finishes before the caller receives the object - so when the caller relinquishes its ownership interest the object may be destroyed before the caller has a chance to declare its interest - not good.
Two solutions are used to address this:
1) The method is declared to transfer ownership interest in its return value from the callee to the caller - this is the model used for
init
,copy
, etc. methods. The callee never notifies it is relinquishing its ownership interest, and the callee never declares ownership interest - by agreement the caller just takes over the ownership interest and the responsibility of relinquishing it later.2) The method is declared to return a value in which the caller has no ownership interest, but which someone else will maintain an ownership interest in for some short period of time - usually until the end of the current run loop cycle. If the caller wants to use the return value longer than that is must declare its own ownership interest, but otherwise it can rely on someone else having an ownership interest and hence the object staying around.
The question is who can that "someone" be who maintains the ownership interest? It cannot be the callee method as it is about to go away. Enter the "autorelease pool" - this is just an object to which anybody can transfer an ownership interest to so the object will stay around for a while. The autorelease pool will relinquish its ownership interest in all the objects transferred to it in this way when instructed to do so - usually at the end of the current run loop cycle.
Now if the above makes any sense (i.e. if I explained it clearly), you can see that method (2) is not really required as you could always use method (1); but, and its a crucial but, under MRC that is a lot more work for the programmer - every value received from a method comes with an ownership interest which must be managed and relinquished at some point - generate a string just to output it? Well you then need to relinquish your interest in that temporary string... So (2) makes life a lot easier.
One the other hand computers are just fast idiots, and counting things and inserting code to relinquish ownership interest on behalf of the intelligent programmers is something they are well suited to. So ARC doesn't need the auto release pool. But it can make things easier and more efficient, and behind the scenes ARC optimises its use - look at the assembler output in Xcode and you'll see calls to routines with name similar to "retainAutoreleasedReturnValue"...
So you are right, its not needed, however it is still useful - but under ARC you can (usually) forget it even exists.
HTH more than it probably confuses!
autorelease
is still used under ARC. ARC just makes the call for you and is clever about short-circuiting it. Here is a demonstration of exactly how that works, which I'll copy here in case that blog post ever disappears; all due credit to Matt Galloway.Difference between ARC and autorelease explained in code :
ARC :
Autorelease :
Basically ARC works once a variable isn't used anymore in a scope, while autorelease waits until it reaches the main loop and then calls
release
on all objects in the pool. ARC is used inside the scope, autorelease is used outside the scope of the function.If autoreleased, it will be added to the autorelease pool. When the autorelease pool is drained, the deferred release will be performed. a function/method does not need to return an autoreleased object (e.g. it could be an ivar which did not receive a retain/autorelease cycle).
It has the potential to. There is no guarantee. The biggest 'problem' here is that the compiler does not know/care the memory mechanics of the returned object of an arbitrary call. It cannot assume how an object is returned because ARC is a new addition which predates MRC. This is important because it makes ARC programs compatible with programs which use manual retain/release. For example, Foundation.framework may use ARC, or it may use MRC, or it may use both. It may also call into APIs which were built using older toolchains. So this has the benefit of keeping a ton of existing code usable.
There's an optional way to return an object -- see CRD's answer (+1) about assembly and the calls the compiler inserts to perform reference count operations e.g.
retainAutoreleasedReturnValue
.In any event, there is no guarantee that lifetimes will always be reduced in ARC. A programmer who understands execution of their program can minimize lifetimes and ref count operations because ARC has stricter lifetime and ownership requirements.
In theory, I don't see why autorelease pools could not be done away with for a new system. However, I think there's too much existing code that relies on autorelease pools to lift that restriction -- I think they would need to phase in a new executable format (as was the case with ObjC Garbage Collection) and review a ton of existing APIs and programs for such a significant transition to succeed. Also, a few APIs would probably just need to be removed. APIs may need some strengthening concerning ownership to accomplish this, but most of that is complete in programs which have already been migrated to ARC. Heck, even the compiler could (be extended to) internally use a form of smart pointers for passing and returning objc types and autorelease pools could be eliminated in such a system. Again, that would require a lot of code to be migrated. So such an upgrade would be like an ARC V2.
Not an issue - autorelease pools are thread local. I don't see an issue beyond that in such a system (unless you are relying on a race condition, which is obviously a bad idea).
You are confusing ARC with reference counting. Objective-C has always relied on reference counting for memory management. ARC continues this tradition and simply eliminates the need for the programmer to manually insert appropriate calls to
-retain
,-release
, and-autorelease
. Under ARC the compiler inserts these calls for you, but the reference counting mechanism remains the same as it has always been.ARC does not eliminate the need for autorelease, but it may be able to avoid it in situations where a human would typically have used it.