Как сделать так, чтобы функция имела доступ к оригинальной структуре без копирования
Что проверяют
Понимаете ли вы семантику значимых типов в Swift и разницу между логической копией и реальным копированием памяти. Следом часто спрашивают, как устроен copy-on-write и почему два inout на одну переменную не компилируются.
Как отвечать
Структура в Swift это тип-значение: присваивание и передача в функцию дают независимую копию по смыслу. При этом обычные параметры функций компилятор передаёт как заимствование, и физически большая структура часто не копируется. Варианты по задаче:
inout: функция может изменить исходное значение, вызывают с&:update(&user). Формально это копирование на входе и запись обратно на выходе, но оптимизатор обычно передаёт адрес напрямую. Переменная должна бытьvar, а неlet;mutatingметод: если изменение логически принадлежит самой структуре, лучшеuser.rename("Bob"), чем свободная функция сinout;- класс или обёртка-бокс: когда нужна общая изменяемая сущность, которую видят несколько владельцев, берут ссылочный тип. Это меняет смысл данных, не только скорость;
borrowingиconsuming: модификаторы параметров, появившиеся в Swift 5.9 вместе с некопируемыми типами~Copyable. Внутриborrowing-параметра неявное копирование запрещено, нужен явныйcopy;withUnsafeMutablePointer(to:): крайний случай для работы с C API, указатель действует только внутри замыкания.
Про коллекции: Array, Dictionary и String используют copy-on-write. Копия дешёвая, буфер дублируется при первой записи, если он не уникален. В своём типе уникальность проверяют через isKnownUniquelyReferenced.
Где спотыкаются
Говорят, что inout это передача по ссылке, как указатель в C. Семантика другая: действует закон эксклюзивного доступа, и перекрывающийся доступ к одной переменной, например swap(&a, &a), компилятор или рантайм отклонит.
Меняют структуру на класс только ради скорости и получают общее изменяемое состояние, гонки данных и ошибки строгой проверки конкурентности Swift 6.
Уверены, что каждая передача структуры копирует байты. Для большинства типов это не так, и преждевременная «оптимизация» через указатели делает код небезопасным без измеримого выигрыша.