Что произойдет, если вы добавите только что созданный объект в изменяемый массив и освободите свой объект?

#objective-c

#objective-c

Вопрос:

Что произойдет, если вы добавите только что созданный объект в изменяемый массив и освободите свой объект?

Ответ №1:

Это зависит. Если вы владели объектом до добавления его в массив, вы все равно должны освободить свое собственное заявление о праве собственности, чтобы избежать утечки — заявление о праве собственности массива на объект является отдельным и не освобождает вас от вашей собственной ответственности в отношении правил управления памятью.

 Object *obj = [[Object alloc] init];
[anArray addObject:obj];
[obj release];
  

С другой стороны, если вы не были владельцем объекта, то вы все еще не являетесь им после добавления в массив и по-прежнему не должны его освобождать. Массив устанавливает свое собственное требование владения, но, как и ваш собственный код, он отвечает за балансировку своих собственных требований.

 Object *obj = [Object object];
[anArray addObject:obj];

// or, avoiding a temp variable

[anArray addObject:[Object object]];
  

Когда вы освободите массив или удалите объект из массива (предполагая, что это изменяемый массив), массив выпустит свое собственное заявление о праве собственности. Вызывающий код не несет дополнительной ответственности за это — массив сделал заявку на владение, поэтому он отвечает за ее освобождение, когда это будет сделано с объектом.

Другими словами, ваша ответственность за освобождение объекта или нет не имеет ничего общего с тем, добавили ли вы его в коллекцию. Ответственность массива также не имеет никакого отношения к тому, что происходит за пределами массива. Это лежит в основе инкапсуляции; каждый класс максимально изолирован от того, что происходит внутри других классов. То, что происходит в NSVegas, остается в NSVegas. 🙂

Ответ №2:

Все в порядке:

   NSMutableArray *array = [[NSMutableArray array] retain];
  Object *obj = [[Object alloc] init];
  [array addObject:obj];
  [obj release];
  

Я создал объект с помощью alloc, init — так что я владелец объекта. Я добавил объект в массив, и массив стал владельцем. Затем я освободил объект. Но у него все еще есть владелец — массив.

Кстати: Если вы освободите массив, объект будет освобожден автоматически.

Комментарии:

1. Обратите внимание, что, поскольку массив становится владельцем объекта, аналогичный код, создающий объект, который не принадлежит вызывающей стороне, также будет работать.

2. Также обратите внимание, что отправка -retain в изменяемый массив не требуется в этом конкретном фрагменте кода.

3. @Bavarious: Если объект не будет принадлежать вызывающей стороне, он будет удален при вызове [obj release], потому что у него будет только 1 счетчик сохранения. В этом случае, я думаю, у вас также возникнет исключение неправильного доступа при освобождении массива.

4. Верно, я пропустил часть ‘освободить ваш объект’. Вы правы: хотя объект все еще был бы активен, потому что он принадлежит массиву, при освобождении самого массива произойдет исключение.

5. Однако суть остается в силе. Если есть удобный метод, который возвращает объект, которому никто не принадлежит, это можно было бы упростить, используя его, вплоть до просто [array addObject:[Object object]] . Да, вызов -release объекта, созданного таким образом, приведет к сбою — так что не делайте этого. 🙂

Ответ №3:

Я бы выделил массив таким образом:

 NSMutableArray *array = [[NSMutableArray alloc] init];
[array retain]

Object *obj = [[Object alloc] init]; //retain count = 1
  

При добавлении объекта количество сохраненных увеличивается до 2

 [array addObject:obj]; 

//When you release the retain count goes to 1 (object still exists)
[obj release];
  

Если вы освободите массив

 [array release];
  

затем количество объектов становится равным 0.