Я думаю, что вы упускаете что-то довольно фундаментальное. Установка объекта на nil
ничего не делает для вас с точки зрения управления памятью. Вот что происходит: альтернативный текст http://gallery.me.com/davedelong/100084/Pointers1/web.png?ver=12783505480001
На этом изображении у вас есть стек (где живут ваши локальные переменные; он более или менее синонимичен тому, где вы находитесь в коде во время выполнения). Если вы объявляете что-то вроде int bar = 42;
, то bar
живет в стеке. Справа у вас куча. Это глобальное пространство памяти, которое принадлежит вашему приложению. Куча была изобретена, чтобы решить проблему области видимости: как заставить полезную информацию жить вне области текущей функции (или метода). Когда мы malloc
пробел, нам назначается слот памяти в куче. Когда вы alloc/init
объект, этот объект живет в куче. В Objective-C все объекты живут в куче. * Итак, давайте рассмотрим эту строку:
MyObject * foo = [[MyObject alloc] init];
У нас действительно есть две вещи. Во-первых, мы выделили (alloc
) новый кусок пространства в куче, достаточно большой, чтобы вместить структуру MyObject
. Затем мы взяли расположение этого блока памяти и присвоили его локальной переменной с именем foo
. На изображении выше красноватый кружок слева - foo
, а красноватый шарик справа - фактический MyObject
(вместе со всеми его данными). Имеет смысл пока?
Вот что происходит, когда вы «устанавливаете объект на nil
» (foo = nil;
)
альтернативный текст http://gallery.me.com/davedelong/100084/Pointers2/web.png?ver=12783505490001
Вы увидите, что объект все еще живет в куче . Фактически, единственное, что изменилось, это то, что ваша локальная переменная foo
больше не указывает на кусок памяти в куче. Он указывает на 0
(nil
, NULL
, как вы хотите это называть), и именно так мы указываем, что «это больше не указывает на что-либо значимое».
В двух словах: установка переменной в nil не имеет ничего общего с управлением памятью . Если вы хотите немедленно избавиться от объекта, используйте release
, а не autorelease
. Однако даже тогда это не гарантированное «немедленное уничтожение», поскольку что-то еще может быть retain
объектом (что составляет весь смысл использования модели управления памятью с сохранением-релизом).
Кроме того, как только вы закончите с объектом (и после того, как вы вызовете release
или autorelease
), все равно будет хорошей идеей установить переменную на nil
, просто чтобы избежать потенциальных проблем. , В Objective-C мы можем безопасно отправлять сообщения на номер nil
, при этом на наших лицах ничего не возникает (в отличие от Java). Однако, если вы не обнуляете переменную, могут произойти плохие вещи. Допустим, foo
указывает на экземпляр MyObject
, а затем экземпляр MyObject
уничтожается (вы release
сделали это, но не установили его на nil
). Если вы попытаетесь снова вызвать метод на foo
, ваше приложение потерпит крах. Если вы установите foo
на nil
, тогда ваше приложение продолжит свой веселый путь. Это может не делать то, на что вы надеялись, но это совсем другая проблема.
Добро пожаловать в удивительный мир управления памятью Objective-C.
* за исключением локальных блоков, но только до тех пор, пока они не будут скопированы. Есть и несколько других предостережений, но это становится загадкой.