tags:

views:

26

answers:

3

When it comes to allocating and initializing objects that are declared @properties of a class I've seen two main patterns in various bits of sample code, so given the following (made up) header code —

@interface Class : Superclass {  
    Object *anObject;  
}  
@property (nonatomic, retain) Object *anObject;  

The first, direct assignment:

self.anObject = [[Object alloc] init];

The second, indirect method creates a temporary object that is then assigned to the property and released:

Object *tempObject = [[Object alloc] init];
self.anObject = tempObject;
[tempObject release];

What's the benefit to the second method over the first?

+3  A: 

The difference between those two blocks of code is that the first one is a memory leak. When you call [Object alloc] you get "ownership" of the object, and are responsible for -releaseing it sometime. Then when you call [self -setAnObject] it takes a second ownership, setting the retain count for the new instance to 2. If the method doing the creation returns without relinquishing its ownership of the new instance, you end up with a leak.

Try this:

self.anObject = [[[Object alloc] init] autorelease];

This works because [NSObject -autorelease] returns self and also schedules a -release call "sometime in the future" which usually means at the end of the current run loop.

Sophistifunk
I'm actually surprised that people are seriously suggesting the first direct assignment approach.
No one in particular
As hotpaw1 mentioned, I did have the first pattern wrong – I've not seen anything using the @property setter method, but I was fuzzy on the difference between self.anObject = [...] vs anObject = [...] anyway. But this makes sense - I'd forgotten that dot syntax affected retain counts.
Mark McDonald
+2  A: 

As a previous poster correctly pointed out, the first method (at least the way it's currently coded) is a memory leak. However the second method is technically more efficient because there's a bit of overhead associated with the autorelease pool.

Adding one extra object to a pool is probably not going to make a measurable difference, but adding lots of objects to a pool unnecessarily might, so in general the second method is preferred.

jlehr
+2  A: 

You may have typo'd the first pattern. The direct assignment (to the instance variable) should be:

anObject = [[Object alloc] init];

bypassing the setter, and thus leaving a proper retain count of 1.

The bad thing is that it avoids the setter (thus causing potential code reuse/enhancement problems).

The good thing is that it avoids the setter (important if this appears in the profile as a hot spot).

hotpaw2
Could you explain a bit more of why avoiding a setter is bad and/or good?
Mark McDonald
It's faster, as you're directly setting the memory, rather than sending a message to self. But by avoiding the message send, you also bypass the runtime magic required for things like KVC, property observers, and bindings.
Sophistifunk