Кто отвечает за освобождение объектов массива при копировании?
-
23-08-2019 - |
Вопрос
Если в Objective-C массив1 копируется в массив2 с помощью mutableCopy и предположим, что код выполняется в функции main(), кто отвечает за освобождение объектов, содержащихся в массиве?Это main() или array2?
Решение
Я думаю, что предыдущие ответы упустили суть, или же автор вопроса был довольно неясен.Фактический вопрос касается не какого-либо массива, а скорее содержимого массива:
кто несет ответственность за выпуск объекты, содержащиеся в массиве?Это main() или array2?
Оба array1
и array2
несут ответственность за освобождение объектов.
«Массивы поддерживают строгие ссылки на свое содержимое — в среде управляемой памяти каждый объект получает сообщение сохранения перед добавлением его идентификатора в массив и сообщение освобождения, когда он удаляется из массива или когда массив освобождается».
Начнем с того, что каждый из объектов сохраняется в NSArray. array1
.Когда вы создаете array2
с помощью -mutableCopy
, вы получаете NSMutableArray, который указывает на одни и те же объекты и снова сохраняет каждый из них.Если бы вы выпустили array1
в этот момент, когда это dealloc
был вызван метод, он освободил бы каждый из содержащихся в нем объектов.Однако, array2
сохранил их, поэтому объекты не будут уничтожены — только тогда, когда их счетчик сохранения достигнет 0, что произойдет, если array2
были уничтожены, и никто больше не сохранил ни одного из объектов (или когда они были удалены из array2
).
Поскольку классы коллекций (массивы, наборы, словари и т. д.) управляют сохранением и освобождением их содержимого, все, о чем вам нужно беспокоиться, — это сохранение или освобождение самой коллекции.Поскольку вы использовали -mutableCopy
, помните, что вы неявно сохранили array2
, поэтому вам следует отпустить его, когда закончите с ним.
Другие советы
Я ссылаюсь это руководство для управления памятью в Obj-C.У него есть раздел «Массивы и словари», вот отрывок:
Массивы, словари и т.д.обычно сохраняют любые добавленные к ним объекты.(При работе со сторонними объектами типа коллекции всегда проверяйте документацию, чтобы узнать, сохраняются они или нет).Это означает, что эти коллекции станут владельцами объекта, и вам не нужно будет сохранять его перед добавлением.
Комментарии к публикации также будут полезны
Обязанности владения не изменяются при хранении объектов в массиве.Вот пример:
int main(int argc, char *argv[])
{
// ...
NSObject *obj1 = [[NSObject alloc] init]; // owned
NSObject *obj2 = [[NSObject alloc] init]; // owned
NSObject *obj3 = [[[NSObject alloc] init] autorelease]; // not owned
NSMutableArray *array1 = [NSMutableArray arrayWithObjects: obj1, obj2, obj3, nil]; // not owned
NSMutableArray *array2 = [array1 mutableCopy]; // owned
// ...
[array2 release];
[obj2 release];
[obj1 release];
// ...
}
Этот код напрямую выделяет obj1
и obj2
, поэтому он владеет ими и должен их освободить, но освобождает автоматически obj3
, поэтому его не обязательно выпускать.Точно так же он не владеет результатом arrayWithObjects:
, поэтому он не освобождает это, но владеет результатом mutableCopy
, поэтому он должен это выпустить.Объекты, хранящиеся в массиве, не имеют значения: все, что вам нужно, — это право собственности.
Оба массива сохраняют строгие ссылки на свое содержимое, поэтому obj1
, obj2
, и obj3
не будет освобождено, пока существуют массивы, но это деталь NSArray
контракт, это не влияет на то, как вы управляете владением объектами или массивами.
Это все детали Соглашения об управлении памятью Cocoa, а не массивы.
Было бы бессмысленно привязывать изменяемый массив к неизменяемому массиву.main() будет отвечать за освобождение массива array1.
Однако, по моему опыту, освобождение объектов приводит только к сбою приложений.ObjC довольно хорошо справляется с автоматическим управлением памятью.Моим приложениям Cocoa, похоже, никогда не требовалось больше памяти, чем было изначально, даже после нескольких часов работы.