Объяснение сильного и слабого хранилища в iOS5


114

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

Я прочитал документацию: Переход на ARC - это ссылки на условия сохранения, назначения и выпуска iOS4; что меня смущает. Затем я смотрю на Open U CS193p, где он различает сильные и слабые:

Сильный : «держите это в куче, пока я не перестану указывать на него»
Слабый : «держите это до тех пор, пока на него сильно не указывает кто-то другой»

Разве эти два определения не идентичны = если указатель больше не указывает на объект, освободить память, содержащую объект? Я понимаю концепцию указателей, кучи, выделения или освобождения памяти, но в чем разница между сильным и слабым?


Модель управления памятью по-прежнему актуальна, даже если вы используете ARC. Вы все еще должны понимать подсчет ссылок, вам просто не нужно делать это вручную. Итак, ваш последний абзац - необоснованное требование.
jrturton

Ответы:


509

Разница в том, что объект будет освобожден, как только на него не будет сильных указателей. Даже если на него указывают слабые указатели, как только последний сильный указатель исчезнет, ​​объект будет освобожден, а все оставшиеся слабые указатели будут обнулены.

Возможно, уместно привести пример.

Представьте, что наш объект - собака, и собака хочет убежать (быть освобожденной).

Сильные указатели похожи на поводок для собаки. Пока собака привязана к поводку, она не убежит. Если пять человек прикрепят поводок к одной собаке (пять сильных указателей на один объект), то собака не убежит, пока не будут сняты все пять поводков.

С другой стороны, слабые указатели похожи на маленьких детей, указывающих на собаку и говорящих: «Смотри! Собака!» Пока собака все еще на поводке, маленькие дети могут видеть собаку и указывать на нее. Однако как только все поводки отсоединены, собака убегает, сколько бы маленьких детей на нее ни указывало.

Как только последний сильный указатель (привязка) больше не указывает на объект, объект будет освобожден, а все слабые указатели будут обнулены.


2
Он основан на аналогии, которую Малком Кроуфорд из Apple привел несколько лет назад. Не знаю, где он это взял.
BJ Homer

Я помню, как читал что-то подобное (до дуги) в книге, думаю, это был Хиллегасс, но тогда он мог бы получить это откуда-то еще ... но это хорошая книга!
jrturton

14
+1 отличный пример. это производное от примера Хиллегасса о том, как поводки удерживаются / отпускаются, но мне нравится эта адаптация для сильных / слабых.
Дэйв Делонг,

2
@DaveDeLong: Ну, они незаконны на 10.6 с ARC. Их вообще нельзя использовать. Так что это неважный момент.
BJ Homer

5
Еще один хороший вариант - воздушные шары с гелием: пока держится хотя бы одна веревка, она не улетит. Аналогии с поводком и воздушным шаром также хороши для того, чтобы заставить людей забыть, что «владение» управляется посредством удержания / освобождения.
Стив Веллер,

34

Разве эти два определения не идентичны.

Точно нет. Ключевое различие между двумя определениями, на которые вы указали, - это «до тех пор, пока кто-то другой». Важно «кто-то другой».

Учтите следующее:

__strong id strongObject = <some_object>;
__weak id weakObject = strongObject;

Теперь у нас есть два указателя <some_object>, один сильный и один слабый. Если мы устанавливаем , strongObjectчтобы nilвыглядеть примерно так:

strongObject = nil;

Затем, если вы выполните изложенные вами правила, вы зададите себе следующие вопросы:

  1. Сильный: «держите это в куче, пока я не перестану указывать на это»

    strongObjectбольше не указывает <some_object>. Так что нам не нужно его хранить.

  2. Слабое: «держите это, пока на это сильно указывает кто-то другой»

    weakObjectвсе еще указывает на <some_object>. Но поскольку на это никто не указывает, это правило также означает, что нам не нужно его соблюдать.

В результате он <some_object>освобождается, и если ваша среда выполнения поддерживает его (Lion и iOS 5 и выше), тогда weakObjectавтоматически будет установлено значение nil.

Теперь посмотрим, что произойдет, если мы сделаем weakObjectэто nilтак:

weakObject = nil;

Затем, если вы выполните изложенные вами правила, вы зададите себе следующие вопросы:

  1. Сильный: «держите это в куче, пока я не перестану указывать на это»

    strongObjectуказывает на <some_object>. Так что нам нужно его сохранить.

  2. Слабое: «держите это, пока на это сильно указывает кто-то другой»

    weakObjectне указывает на <some_object>.

Результатом является то , что <some_object>это не освобождаться, но weakObjectбудет nilуказатель.

[Обратите внимание, что все, что предполагается <some_object>, не указано в другой сильной ссылке где-то еще / каким-либо другим способом «удержания»]


1
Таким образом, основное различие между сильным и слабым состоит в том, что освобождение объектов, на которые указывает строго, автоматически обнуляет все связанные слабые указатели. И для слабого указателя, указывающего на что-то, всегда существует сильный указатель. Если да, то на главный объект приложения нужно четко указывать?
KMC

Чтобы слабый указатель указывал на что-то действительное, тогда да, должен быть сильный указатель. Добавьте к этому тот факт, что iOS 5 и Lion поддерживают автоматическое заполнение слабых ссылок, и вы получите то, что говорите. Однако среда выполнения iOS 4 не поддерживает это. "Главный объект приложения", я полагаю, вы имеете в виду UIApplicationобъект? На это будет сильно ссылаться внутренняя работа UIKit- но вам не нужно об этом беспокоиться.
mattjgalloway

Я думаю, вы можете использовать такое слово как "strongObjectPointer" вместо "strongObject". Так что у новичков в программировании будет больше смысла. Хороший улов на посте @BJ Homer, мистер Мэтт. Интересно :)
Vijay-Apple-Dev.blogspot.com

2

сильный

  1. Создает право собственности между свойством и присвоенным значением.
  2. Это значение по умолчанию для свойства объекта в ARC, поэтому оно не позволяет вам беспокоиться о счетчике ссылок и автоматически освобождать ссылку.
  3. Это замена для сохранения. Мы используем тогда и только тогда, когда нам нужно использовать as keep.

слабый

  1. Создает не владение между свойством и присвоенным значением.
  2. Strong используется для родительского объекта, а weak - для дочернего объекта, когда родительский объект освобождается, тогда ссылка на дочерний объект также устанавливается на ноль
  3. Это помогает предотвратить сохранение циклов.
  4. Он не защищает указанный объект при сборке сборщиком мусора.
  5. Слабое по существу заданное, несохраняемое свойство.

Здесь стоит упомянуть, что обычно представляет собой цикл сохранения. У нас есть два объекта: объект A и объект B. Объект A имеет сильную ссылку на объект B, а объект B имеет сильную ссылку на объект A. Ничто другое не имеет сильной ссылки на объект A или B.
boro

2

Другой пример: Objectпредполагается, что студент может получить высшее образование ( deallocate), если он / она закончил все основные курсы ( strong pointers), независимо от того, принимает ли он / она дополнительные курсы ( weak pointers). Другими словами: сильный указатель - единственный фактор, освобождающий его Object.


1

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


1

Я знаю, что довольно опаздываю на эту вечеринку, но я думаю, что важно запутать проблему, указав, что значение «сильных и слабых моделей памяти» зависит от того, о программном или аппаратном обеспечении вы говорите.

Для оборудования "слабый" или "сильный" указывает, поддерживается ли последовательная согласованность.

[SC означает, что] ... результат любого выполнения такой же, как если бы операции всех процессоров были выполнены в некотором последовательном порядке, и операции каждого отдельного процессора появляются в этой последовательности в порядке, указанном его программой. - Лэмпорт, 1979.

Какого черта это связано с памятью? Это означает, что записи в переменные разными процессорами должны выполняться всеми процессорами в одном и том же порядке. В оборудовании с сильной моделью это гарантировано. На оборудовании со слабой моделью это не так.

Существующие ответы интерпретируют вопрос только с точки зрения программных моделей памяти. Аппаратное обеспечение не имеет отношения к программированию. Именно в этом вопросе упоминается iOS, которая обычно работает на процессорах Arm7. Arm7 имеет слабую модель памяти. Для программистов, привыкших к процессорам с сильной моделью - а это все мы, потому что x86 и x64 имеют сильную модель - это ужасная ловушка. Использование bool для сигнализации выхода другому потоку отлично работает в сильной модели. Тот же код на Arm вообще не работает, если вы не отметите флаг как изменчивый, и даже в этом случае он неустойчив.

Хотя это правда, что Arm8 + полностью меняет это с явной поддержкой приобретения / выпуска, устаревшее программное обеспечение не использует эту поддержку. Устаревшее программное обеспечение включает все три ОС телефона и все, что на них работает, а также компиляторы и библиотеки, пока они не будут обновлены.

Для более подробного изучения этой темы я отсылаю вас к неподражаемому Herb Sutter .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.