薄情王爷的宠妃大结局:cocoa - Object allocate and init in Objective C - Stack Overflow

来源:百度文库 编辑:九乡新闻网 时间:2024/04/20 06:37:27

Object allocate and init in Objective C

up vote 20 down vote favorite 18

What is the difference between the following 2 ways to allocate and init an object?

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

and

self.aController= [[AController alloc] init];

Most of the apple example use the first method. Why would you allocate, init and object and then release immediately?

objective-c cocoa cocoa-touch memory-management link|edit|flag edited Apr 7 '10 at 19:10
asked Oct 1 '08 at 4:31 Ronnie Liew
1,93541127
91% accept rate

7 Answers

activeoldestvotes up vote 28 down vote accepted

Every object has a reference count. When it goes to 0, the object is deallocated.

Assuming the property was declared as @property (retain):

Your first example, line by line:

  1. The object is created by alloc, it has a reference count of 1.
  2. The object is handed over to self's setAController: method, which sends it a retain message (because the method doesn't know where the object is coming from), incrementing its reference count to 2.
  3. The calling code no longer needs the object itself, so it calls release, decrementing the reference count to 1.

Your second example basically does steps 1 and 2 but not 3, so at the end the object's reference count is 2.

The rule is that if you create an object, you are responsible for releasing it when you're done with it. In your example, the code is done with tempAController after it sets the property. It is the setter method's responsibility to call retain if it needs that object to stick around.

It's important to remember that self.property = foo; in Objective-C is really just shorthand for [self setProperty:foo]; and that the setProperty: method is going to be retaining or copying objects as needed.

If the property was declared @property (copy), then the object would have been copied instead of retained. In the first example, the original object would be released right away; in the second example, the original object's reference count would be 1 even though it should be 0. So you would still want to write your code the same way.

If the property was declared @property (assign), then self isn't claiming ownership of the object, and somebody else needs to retain it. In this case, the first example would be incorrect. These sorts of properties are rare, usually only used for object delegates.

link|edit|flag edited Oct 22 '08 at 15:16
answered Oct 1 '08 at 4:54 benzado
7,13521242 This is only the case if 'aController' is declared with the @property(retain) though, right? – Mike F Oct 1 '08 at 5:00 That is correct. – Hans Sjunnesson Oct 1 '08 at 5:28 It’s also the correct pattern if the property is declared (copying). The second pattern is correct for a property declared (assign) (or with garbage collection enabled). – Ahruman Oct 1 '08 at 9:30 This is the "accepted" answer, but I strongly advise you to read mmalc's answer below, too. It shows how to do this in a more practical manner (with a tiny, tiny, tiny performance effect). – Adam Aug 6 '10 at 7:41 up vote 16 down vote

As others have noted, the two code snippets you show are not equivalent (for memory management reasons). As to why the former is chosen over the latter:

The correct formulation of the latter would be

self.aController= [[[AController alloc] init] autorelease];

Compared with the former, this adds additional overhead through use of the autorelease pool, and in some circumstances will lead to the lifetime of the object being unnecessarily extended (until the autorelease pool is released) which will increase your application's memory footprint.

The other "possible" implementation (depending on where the example is from) is simply:

aController = [[AController alloc] init];

However, setting an instance variable directly is strongly discouraged anywhere other than in an init or dealloc method. Elsewhere you should always use accessor methods.

This brings us then to the implementation shown in sample code:

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

This follows best practice since:

  • It avoids autorelease;
  • It makes the memory management semantics immediately clear;
  • It uses an accessor method to set the instance variable.
link|edit|flag answered Oct 3 '08 at 16:37 mmalc
5,25611234 2   mmalc's right. But ... in practice, 3 lines of code to assign to 1 variable is simply insane. Most teams I've seen use the autorelease "do it all in a single line of code" approach - the overhead is VANISHINGLY small. If you ever hit a situation on iPhone where it makes a significant performance difference, you should probably be rewriting that code in C anyway - you're doing too much allocation. Few teams will stick to the "official" convention (rightly so IMHO - real-world programs should be clear, but not to the point of verbal diarrhoea). – Adam Aug 6 '10 at 7:40 up vote 4 down vote

Note also that your desire to cut the code down to one line is why many people use Autorelease:

self.aController = [[[AController alloc] init] autorelease];

Though in theory on the iPhone autorelease is somehow more expensive (never heard a clear explanation why) and thus you may want to explicitly release right after you assign the object elsewhere.

link|edit|flag answered Oct 1 '08 at 7:03 Kendall Helmstetter Gelner
20.5k22346 I dont think it is more expensive than autorelease in Cocoa. Just that autorelease is more expensive than release. So if you can release the object instead of autoreleasing you should do so. – schwa Oct 1 '08 at 14:53 autorelease is more expensive because it has to find a thread-local data structure and add to it (the autorelease pool), whereas release just decrements an integer (the reference count). – benzado Oct 2 '08 at 0:38 @benzado: Yes, the question was why is autorelease more expensive on the iPhone, not why it is more expensive than release. – Sergio Acosta Oct 10 '08 at 20:27 I never autorelease unless I have to.. – Mk12 Aug 17 '09 at 1:53 up vote 2 down vote

One other thing to note is that your example depends on the @property definition of aController also.

If it were defined as @property (readwrite, retain) id aController; then your example works, while if it is defined as @property (readwrite, assign) id aController; then the extra call to release would cause your object to be deallocated.

link|edit|flag answered Oct 1 '08 at 18:38 Ashley Clark
2,652217 There's no point of specifying readwrite, since it is the default. – Mk12 Aug 4 '09 at 0:19 up vote 0 down vote

You could also do

@property (nonatomic, retain)AController *aController;
...
self.aController= [[AController alloc] init];
[aController release];

with a retaining property, and it would function the same way, but its better to use the other way (for retaining properties) because it's less confusing, that code makes it look like you assign aController and then it gets deleted from memory, when actually it doesn't because setAController retains it.

link|edit|flag answered Aug 4 '09 at 0:24 Mk12
1,61321346 It'd be even worse if this were a copying property. You'd be releasing the copy, leaving a dead object in the instance variable, and leaking the object you allocked and inited. – Peter Hosey Aug 4 '09 at 0:48 But it does work if it's retaining. Not that you should do that. – Mk12 Aug 17 '09 at 1:54 up vote 0 down vote

If you're using Xcode, it can help you detect such code with the static analyzer. Just hit Build >> Build and Analyze

This will show you a very helpful message at such pieces of code.

link|edit|flag answered Jan 14 at 18:07 Colins
48039 up vote -11 down vote

I'm just a C++ programmer, but I'd bet the first may use heap space whereas the second should only use stack...

link|edit|flag answered Oct 1 '08 at 4:35 Nowhere man
1,183139 1   You would lose the bet. Objective-C objects are always allocated on the heap. – benzado Oct 1 '08 at 4:56 Good to know... I should take a look at Objective-C some day, just for the sake of curiosity. – Nowhere man Oct 1 '08 at 21:44