Что копируется, а что передается по ссылке в Swift
Что проверяют
Понимаете ли вы модель значений в Swift и её последствия: где изменение видно только вам, а где расходится по всему приложению. Ответ показывает и готовность к разговору про многопоточность и подсчёт ссылок, потому что следующий вопрос почти всегда оттуда.
Как отвечать
Разделить типы на две группы:
- типы значений: структуры, перечисления, кортежи. Сюда же относятся
Array,Dictionary,SetиStringиз стандартной библиотеки: при присваивании и передаче в функцию значение копируется; - ссылочные типы: классы, замыкания, акторы. Копируется ссылка, объект остаётся один, и правку через любую ссылку видят все владельцы. Именно за ними следит
ARC.
Дальше стоит сказать про две тонкости, ради которых вопрос и задают. Первая: коллекции используют копирование при записи, то есть буфер разделяется до первой мутации и копируется только тогда, когда на него ссылается кто-то ещё. Вторая: копия структуры поверхностная, поля-классы внутри остаются общими.
final class Box { var value = 1 }
struct Holder { var box = Box(); var count = 0 }
var a = Holder()
var b = a
b.count = 5 // у a осталось 0
b.box.value = 42 // a.box.value тоже стал 42Где спотыкаются
Говорят, что передача массива в функцию дорогая, потому что он копируется. Копируется только заголовок, а буфер разделяется, пока кто-то не начнёт писать. Оптимизация на этом месте обычно лишняя.
Не видят разницы между копией структуры и её содержимым. Пример выше и есть любимое продолжение вопроса: значение скопировали, а объект внутри общий, и правка из одной копии приходит в другую.
Путают ссылочность с изменяемостью. Объявленный через let объект класса менять можно, нельзя лишь переприсвоить саму ссылку. Со структурой наоборот: let замораживает значение целиком, и мутирующий метод у неё не вызвать.