Как работает copy-on-write в Swift
Вопрос
Расскажите, как устроен copy-on-write и где он есть в Swift.
Попробуйте сами
Ответьте вслух за 2 минуты, как на собесе. Потом сверьтесь с тезисами: что прозвучало, а что нет.
Показать ответ и разбор
Коротко
Что должно прозвучать в ответе
Присваивание коллекции не копирует элементы, обе переменные делят буфер
Перед мутацией проверяется уникальность ссылки на буфер (`isKnownUniquelyReferenced`)
Если буфер общий, он копируется, затем меняется копия
Есть у `Array`, `Dictionary`, `Set`, `String`; у своих структур автоматически нет
Свою реализацию делают через приватный класс-хранилище
Что могут спросить следом
- Что будет с производительностью, если мутировать копию в цикле?
- Почему
isKnownUniquelyReferencedне работает с ObjC-объектами?
Разбор
Copy-on-write это оптимизация типов значений с большим хранилищем. Структура Array хранит ссылку на буфер в куче. Когда я пишу var b = a, копируется только эта ссылка, счётчик ссылок буфера становится 2. Перед любой мутацией массив вызывает isKnownUniquelyReferenced: если ссылка единственная, меняет буфер на месте, если нет, сначала копирует буфер, и дальше у каждой переменной свой. Снаружи это выглядит как обычная семантика значения, но без лишних копий. Так работают Array, Dictionary, Set и String. Мои структуры этого сами не умеют: если внутри большой класс-хранилище, я должен сам проверять уникальность в мутирующих методах. Ловушка: если держать лишнюю копию массива, каждая первая мутация будет стоить O(n).
Ответьте сами, а не прочитайте
В тренажёре вопрос попадёт в повторения и вернётся, когда начнёт забываться. Плюс билеты с зачётом: 20 вопросов, не больше 2 ошибок.
Предыдущий вопрос
Что выведет Swift: структура с классом внутри
Следующий вопрос
Чем struct отличается от class в Swift
Ещё по теме «Типы значений и ссылочные»
- Copy-on-write у Array: когда копируется буфер
- Модификаторы borrowing и consuming
- Как сделать свой copy-on-write
- Existential container: как хранится any Protocol
- Типы значений и ссылочные типы в Swift
- Оператор === в Swift
- Зачем indirect у enum
- Задача на Swift: стек отмены для текстового поля