С выходом Swift 5.5 в язык была интегрирована концепция ownership model и move semantics, которые усиливают контроль над владением данными и позволяют компилятору оптимизировать перемещения, уменьшая количество копирований, что актуально для высокопроизводительных сценариев.
Move semantics подразумевает, что при передаче значения (например, struct) можно "передать" владение этим значением без копирования. При этом компилятор может инвалидировать исходную переменную (аналог move в C++). Сейчас ownership model и move semantics больше реализованы как эксперимент (actor isolation, sendable types, @_move, consuming/self-consuming) и обещают появиться в публичном API.
Основное отличие от ARC — move semantics применимо к value types, тогда как ARC управляет временем жизни объектов-ссылок.
Пример (семантика владения, Swift 5.5+):
func consume<T>(_ x: __owned T) { /* ... */ } struct LargeArray { var storage: [Int] mutating func clear() { storage.removeAll() } consuming func consumeSelf() { // self недоступен после вызова } }
Управление владением позволяет избежать неожиданных копий при работе с большими структурами.
Нюансы:
В чем отличие передачи объекта структуры в функцию по значению, по ссылке и по move semantics в Swift?
Ответ:
Пример:
func foo(_ x: MyStruct) { /* копия */ } func bar(_ x: inout MyStruct) { /* по ссылке */ } func baz(_ x: __owned MyStruct) { /* move semantics, не копирует */ }
История
В проекте при передаче больших структур через функции всегда происходило неявное копирование, увеличивая затраты памяти. После внедрения experimental move semantics и более продуманного управления владением удалось чисто перераспределить нагрузку и ускорить критические участки.
История
Многие разработчики неверно использовали inout, считая, что он реализует move, в то время как значение остается доступным, и возникает неоднозначное владение переменной, приводя к багам и нарушению логики.
История
Ошибка управления данными между потоками: отсутствие квалификатора Sendable на структурах, что приводило к неожиданному копированию или ошибкам владения при асинхронной работе с большими структурами через actor или Task.