Что такое copy-on-write и как он работает
Что проверяют
Понимаете ли вы, что копирование значимого типа в Swift ленивое, и знаете ли, когда оно всё-таки происходит.
Как отвечать
Copy-on-write это приём, при котором копия данных создаётся не в момент присваивания, а в момент первого изменения. Так устроены Array, String, Dictionary и Set.
var a = [1, 2, 3]
var b = a // копии нет, оба ссылаются на один буфер
b.append(4) // вот здесь буфер копируетсяВнутри это работает через подсчёт ссылок на буфер: перед изменением проверяется isKnownUniquelyReferenced, и если владелец один, изменение идёт на месте, без копирования.
Зачем: значимые типы дают безопасную семантику, никто не изменит ваш массив из другого места, но полное копирование при каждой передаче в функцию было бы слишком дорого. Copy-on-write даёт и то и другое.
Что из этого следует на практике: передавать большой массив в функцию дёшево, пока функция его не меняет. А цикл, который в каждой итерации меняет копию массива, наоборот, вызовет копирование на каждом шаге.
То же самое можно сделать в своём типе: положить данные в класс-хранилище и перед мутацией проверять уникальность ссылки, копируя буфер при необходимости.
Где спотыкаются
Считают, что присваивание массива сразу копирует данные.
Не знают про isKnownUniquelyReferenced и не могут объяснить, как система понимает, что пора копировать.
Забывают, что copy-on-write не спасает при передаче в замыкание, которое захватывает и меняет.
Путают это с ленивыми вычислениями: копирование откладывается, а не вычисление.