Что копируется, а что передается по ссылке в Swift
Что проверяют
Различаете ли типы-значения и ссылочные типы и знаете ли про копирование при записи. Проверяют не термины, а последствия: где изменение видно снаружи, и правда ли передача большого массива стоит дорого.
Как отвечать
Структуры, перечисления и кортежи это типы-значения: при присваивании и передаче в функцию копируется содержимое. Классы, замыкания, функции и акторы это ссылочные типы: копируется ссылка, объект остаётся один, и правка через любую ссылку видна через все остальные. Важная деталь для собеседования: String, Array, Dictionary и Set в Swift реализованы структурами, то есть это тоже значения, а не ссылки.
Дальше главное. Коллекции и строки используют копирование при записи: при присваивании буфер не дублируется, копия создаётся лениво, в момент первой записи, и только если на буфер больше одной ссылки. Поэтому утверждение «передача массива копирует мегабайты» это миф, пока копию не изменяют.
Формально по ссылке в Swift не передаётся ничего: всё передаётся по значению, просто у класса это значение и есть ссылка. Настоящая передача самой переменной делается через inout.
struct P { var x = 0 }
var a = P(); var b = a; b.x = 1 // a.x == 0
final class C { var x = 0 }
let c1 = C(); let c2 = c1; c2.x = 1 // c1.x == 1Где спотыкаются
Относят String и Array к ссылочным типам по интуиции «они большие, копировать дорого». Копирование при записи как раз и придумано, чтобы совместить семантику значения с дешёвой передачей.
Путают let с неизменяемостью объекта. У класса let запрещает заменить ссылку, но свойства менять можно. У структуры let запрещает и менять свойства, поэтому метод, помеченный mutating, на такой переменной просто не вызовется.
Не помнят, что замыкание захватывает self сильной ссылкой. Объект, который хранит замыкание, ссылающееся на него самого, не освобождается никогда. Лечится списком захвата со слабой или бесхозной ссылкой, и об этом спрашивают почти всегда сразу следом.