2

from: In which situations do we need to write the __autoreleasing ownership qualifier under ARC?

  • ( BOOL )save: ( NSError * __autoreleasing * );

The compiler will then have to create a temporary variable, set at __autoreleasing. So:

NSError * e = nil;
[ database save: &error ];

Will be transformed to:

NSError __strong * error = nil;
NSError __autoreleasing * tmpError = error;
[ database save: &tmpError ];
error = tmpError;

Okay, now the transformed code seems to work just fine. At the end I expected that it'll work properly despite a "little" (very little) bit in efficient. So why bother specifying autoreleasing?

To be more exact. I understand that we "should" use __autoreleasing when we pass on pointer to pointer. However, if the only thing we got is just a very slight performance gain, then what's the point?

Community
  • 1
  • 1
user4951
  • 32,206
  • 53
  • 172
  • 282

1 Answers1

1

You are missing what actually happens in this code when a variable is passed by reference and assigned in an ARC program.

In non-ARC Programming, the save function looks like this:

- (BOOL)save:(NSError * __autoreleasing *)myError {
  *myError = [[[NSError error] retain] autorelease]
}

In ARC Programming, the save function looks like this:

- (BOOL)save:(NSError * __autoreleasing *)myError {
  *myError = [[NSError alloc] init];
}

Despite what the ARC code looks like, both save functions create an error object that has been retained and autoreleased.

This is because in the ARC version, the type of pointer that myError is determines what happens with the memory management of the error object. In effect, as long as the pointer is type __autoreleasing, the *myError assignment line is replaced with

*myError = [[[NSError error] retain] autorelease]

at runtime.

So if we were somehow able to pass in a pointer of the wrong type to the save function, it would cause the save function to do the wrong thing.

Since the compiler will create a temporary variable in your example, your code will work either way, but the first version does not make sense from an ARC programming perspective.

Colin
  • 2,089
  • 25
  • 34
  • +1 but it's till not clear. So you said that my method will work anyway? So if it works anyway, why bother declaring it differently? Also a smart compiler would produce efficient code anyway. – user4951 Sep 21 '12 at 03:38
  • Your method works because the autoreleased temporary variable will be autoreleased at the end of the run loop [or before], and the strong reference will be released when it goes out of scope [or thereabouts], and then the object will be deallocated. The important point here is that you are _creating_ the *pointer* that the save function will use, so you must give it a reference to the right kind of pointer. If the save function instead returned the error like this: myError = [self save];, then _it_ would create the pointer internally, and so there would be no need for a temporary variable. – Colin Sep 21 '12 at 13:18
  • You sure the code work? So the advantage of using __autoreleasing is simply a slightly faster code? – user4951 Sep 22 '12 at 14:32
  • Your answer is good, but could you make it more relevant to the question especially the last paragraph? – user4951 Sep 24 '12 at 15:28
  • Yes it works. You're right maybe it is not relevant to your question. – Colin Sep 24 '12 at 15:40