Имеет ли ARC счет для неподтвержденной ссылки?
Правда ли, что ARC ведет подсчет неиспользованных ссылок на объект?
Итак, если счетчик строгих ссылок объекта достигает 0, а число ссылок на этот объект, не являющееся владельцем,> 0, объект деинициализируется, но не выделяется? И только когда счетчик сильных и неподтвержденных ссылок достигает 0, он перераспределяется?
Я читал это в статье, на Medium, я думаю), но я не уверен, что это правильно.
2 ответа
Прежде всего, давайте будем знать, что ответы на эти вопросы - все детали реализации, на которые мы должны вообще не полагаться. Теперь перейдем к ответам:
Правда ли, что ARC ведет подсчет неиспользованных ссылок на объект?
Да, это правда. Каждый объект имеет три счетчика ссылок: сильный счет, счетчик не владеющих и слабый счет.
Сильный счет всегда сохраняется (но сохраняется с регулировкой -1, поэтому сохраненный 0 означает счетчик сильных ссылок, а сохраненный 1 означает счетчик сильных ссылок 2 и т. Д.).
Неизвестный счетчик также всегда сохраняется с поправкой +1, которая представляет все сильные ссылки и удаляется в конце деинициализации.
Счетчик слабых ссылок сохраняется только после создания первой слабой ссылки на объект. Счетчик слабых ссылок, если он хранится, сохраняется с настройкой +1, которая представляет все неиспользованные ссылки и удаляется после освобождения объекта.
Итак, если счетчик строгих ссылок объекта достигает 0, а число ссылок на этот объект, не являющееся владельцем,> 0, объект деинициализируется, но не выделяется?
Правильный. Объект деинициализирован: deinit
s класса объекта и всех суперклассов выполняются, и любые свойства объекта, которые сами являются ссылками, устанавливаются в nil. Однако память объекта не освобождается, поскольку заголовок объекта должен оставаться действительным до последнего unowned
ссылка на объект уничтожена.
И только когда счетчик сильных и неподтвержденных ссылок достигает 0, он перераспределяется?
Правильный. Объект освобождается, когда количество как сильных, так и не принадлежащих ссылок достигает нуля. Поскольку на большинство объектов никогда не ссылаются unowned
ссылки, это обычно, когда последняя сильная ссылка уничтожается.
Вы не спрашивали о слабых ссылках, но для полноты я также объясню их. Когда на объект (или когда-либо) ссылались слабо, Swift выделяет для объекта то, что он называет "записью боковой таблицы" (или иногда просто "боковой таблицей").
Если у объекта нет таблицы сторон, то сильные и неизвестные значения сохраняются непосредственно в объекте, а слабые значения (которые должны быть равны нулю) не сохраняются.
Если у объекта есть таблица сторон, в нем сохраняется указатель на таблицу сторон. Сильные, неизвестные и слабые счета и указатель на объект сохраняются в боковой таблице.
Слабая ссылка на объект сохраняется как указатель на таблицу сторон, а не на объект. Это означает, что объект может быть освобожден (не только деинициализирован), даже если на него все еще имеются слабые ссылки.
Боковая таблица освобождается, когда объект освобождается, если нет слабых ссылок на объект. Если все еще имеются слабые ссылки, объект освобождается, но дополнительная таблица остается выделенной. Когда последняя слабая ссылка на освобожденный объект уничтожается, боковая таблица освобождается.
Обратите внимание, что слабые ссылки не устанавливаются равными nil (уничтожаются) немедленно, когда объект Swift деинициализирован или освобожден! Слабая ссылка на деинициализированный объект устанавливается на ноль только тогда, когда программа пытается загрузить ссылку, или когда контейнер слабой ссылки деинициализирован. (То, что я имею в виду под "контейнером", это, например, когда объект имеет weak var
имущество. Объект является контейнером weak var
ссылка.)
Большой комментарий вверху RefCount.h
в исходном коде Swift объясняются все эти детали и многое другое.
PS Есть еще один вид ссылки, unowned(unsafe)
, который не регулирует количество ссылок. Вы должны избегать такого рода ссылок, если это вообще возможно (и избегание почти всегда возможно).
Слабые и неподтвержденные ссылки позволяют одному экземпляру в ссылочном цикле ссылаться на другой, не удерживая его крепко.
strong
ссылки добавляют 1 к сильному количеству ссылок.
weak
а также unowned
НЕ добавляйте 1 к сильному количеству ссылок.
Как только объект имеет 0 сильных ссылок, ARC деинициализирует его.
Если вы попытаетесь получить доступ к неизвестному свойству, которое относится к деинициализированному объекту, вы вызовете ошибку времени выполнения, сравнимую с принудительным развертыванием необязательного типа nil.
Документы: документация ARC