1

I have these little piece of code:

Person *person1 = [[Person alloc] init];
person1.name = @"Meier";
[personArray addObject:person1];
[person1 release];

When I create the object, add it to the array and send release the person1 is only retained by the array. The array become the owner and responsible for the person1. But when I create the person1 with new it is added to the autorelease pool and I should not send a release to it.

How to I make the array responsible for the person? Only the array?!

EDIT

I guess I was very confused this evening.

YES, objects created with new are not added to the autoreleasepool automatically.

YES, I know I still have to release objects created with new.

I forgot it all for a moment. Thanks a lot for the answers!

TalkingCode
  • 13,407
  • 27
  • 102
  • 147

2 Answers2

3

First of all [Person new] is a shorthand for [[Person alloc] init], not [Person person] (which by convention should return an autoreleased instance).

[Foo new]; //-> retained (you're among the owners)
[[Foo alloc] init]; //-> retained (you're among the owners)
[[Foo alloc] initWithBar:@"bar"]; //-> retained (you're among the owners)
[[[Foo alloc] init] autorelease]; //-> retained, then autoreleased (you're not among the owners)
[Foo foo]; //-> autoreleased (you're not among the owners)
[Foo fooWithBar:@"bar"]; //-> autoreleased (you're not among the owners)

This being said your code is totally doing what you're wanting it to do.

  1. Creating a local instance person1 of person with yourself as its owner.
  2. Adding it to the array (making the array a second owner of person1)
  3. Releasing person1 (removing yourself from person1's owners)
  4. Resulting in an instance of Person whose only (current) owner is the array.

As soon as the array gets deallocated it will call [person1 release], which then will call [self dealloc], as its retain count reached 0. (In case you're wondering why for some magical reason your person1's retainCount is not 1 after step "4.": read this)

These code snippets are basically functionally equivalent:

//Alloc, init, assign name, then release:
Person *person1 = [Person new];
person1.name = @"Meier";
[personArray addObject:person1];
[person1 release];

//Alloc, init, assign name, then release:
Person *person1 = [[Person alloc] init];
person1.name = @"Meier";
[personArray addObject:person1];
[person1 release];

//Alloc, init with argument name, then release:
Person *person1 = [[Person alloc] initWithName:@"Meier"];
[personArray addObject:person1];
[person1 release];

//Alloc, init with argument, assign name, then autorelease:
Person *person1 = [[[Person alloc] init] autorelease];
person1.name = @"Meier";
[personArray addObject:person1];

//Alloc, init with argument name, then autorelease:
Person *person1 = [[[Person alloc] initWithName:@"Meier"] autorelease];
[personArray addObject:person1];

//Use autoreleased convenience method:
Person *person1 = [Person person];
person1.name = @"Meier";
[personArray addObject:person1];

//Use autoreleased convenience method with argument name and add its result to array right away and anonymously:
[personArray addObject:[Person personWithName:@"Meier"]];

Thea all result in person1 being owned only by array and by the NSAutoreleasePool (if one exists, which should be the case for the latter 4 snippets) and only until the pool gets drained.

Community
  • 1
  • 1
Regexident
  • 29,441
  • 10
  • 93
  • 100
2

But when I create the person1 with new it is added to the autorelease pool and I should not send a release to it.

According to the rules, the above is incorrect. If you use new to create a Person, you're still responsible for releasing the resulting object.

However, let's assume for the sake of argument that somehow you create an instance of Person that's autoreleased. In that case, you just don't release the object. If you add it to an array, the array will retain the object as usual and will be responsible for releasing it when it's done with that object.

Caleb
  • 124,013
  • 19
  • 183
  • 272