Ответ
Copy-on-Write (CoW) оптимизирует работу со value-типами, откладывая копирование данных до момента их реальной модификации. Реализуется через комбинацию struct и внутреннего ссылочного типа (class).
Базовая реализация:
// 1. Класс-хранилище (ссылочный тип)
final class Ref<T> {
var value: T
init(_ value: T) { self.value = value }
}
// 2. Публичная структура (value-тип) с CoW
struct CoWBox<T> {
private var ref: Ref<T>
init(_ value: T) {
ref = Ref(value) // Создаем единственную ссылку
}
var value: T {
get { ref.value } // Чтение — используем общие данные
set {
// Ключевой момент: копируем только если ссылка не уникальна
if !isKnownUniquelyReferenced(&ref) {
ref = Ref(newValue) // Создаем новое хранилище
return
}
// Если ссылка уникальна — модифицируем существующие данные
ref.value = newValue
}
}
}
Как это работает:
CoWBox— это структура. При присваивании (let box2 = box1) копируется только ссылкаref, а не сами данные.- При чтении
valueданные используются напрямую из общего хранилища. - При записи в
valueпроверяется функцияisKnownUniquelyReferenced(&ref). Она возвращаетtrue, если на объектRefесть только одна ссылка (этот экземплярCoWBox— его единственный владелец).- Если
true— можно безопасно менять данные «на месте». - Если
false— значит, данные разделяют другие экземплярыCoWBox. Создается новый объектRefс новым значением, и дальнейшие изменения не затронут другие копии.
- Если
Где используется: Именно так реализованы стандартные коллекции Swift (Array, Dictionary, Set, String), что делает их эффективными при передаче по значению.
Ответ 18+ 🔞
Да ты посмотри, какая хитрая жопа этот Copy-on-Write! Ну реально, гениальная, блядь, оптимизация для структур. Суть-то проще пареной репы, если не загоняться.
Вот представь: у тебя есть здоровенный массив, и ты его в десять функций передаёшь. Если бы он каждый раз копировался — пипец, производительность накрылась бы медным тазом. А CoW говорит: «Да похуй, чувак, копируй смело!». Но копирует он не данные, а только... ссылочку! Ёпта, как так?
Вот как это под капотом устроено, блядь:
// 1. Класс-хранилище (ссылочный тип)
final class Ref<T> {
var value: T
init(_ value: T) { self.value = value }
}
// 2. Публичная структура (value-тип) с CoW
struct CoWBox<T> {
private var ref: Ref<T>
init(_ value: T) {
ref = Ref(value) // Создаем единственную ссылку
}
var value: T {
get { ref.value } // Чтение — используем общие данные
set {
// Ключевой момент: копируем только если ссылка не уникальна
if !isKnownUniquelyReferenced(&ref) {
ref = Ref(newValue) // Создаем новое хранилище
return
}
// Если ссылка уникальна — модифицируем существующие данные
ref.value = newValue
}
}
}
Алгоритм работы — волнение ебать:
- Создаёшь
CoWBox— внутри рождается одинокий объектRefс данными. - Копируешь структуру (
let второйЯщик = первыйЯщик). Что скопировалось? Да нихуя! Только ссылкаrefна тот же самый внутренний класс. Данные-то одни на двоих! - Читаешь значение — всё ок, берётся из общего хранилища. Все довольны.
- А вот когда пытаешься записать — тут начинается магия. Вызывается эта хитрая функция
isKnownUniquelyReferenced(&ref). Она, сука, как сторожевой пёс, проверяет: «А не делим ли мы эти данные с кем-то ещё?».- Если ссылка уникальна (никто больше на неё не смотрит) — да ради бога, меняй данные на месте! Кто тебе запретит?
- Если ссылка НЕ уникальна (ой, а там уже
второйЯщикподглядывает) — тут-то и срабатывает «copy» из названия! Создаётся новый объектRefс новыми данными, и уже в него идёт запись. Старые данные остаются нетронутыми для других пользователей. Красота, блядь!
Где это, спрашивается, применяется? Да везде, сука! Все стандартные коллекции Swift — Array, Dictionary, Set — они именно так и работают. Выглядят как value-типы, ведут себя как value-типы, но пока их не трогаешь — они все сидят на одной общей куче данных, как мартышлюшки. А тронул — получи свою личную копию. Удобно, эффективно, в рот меня чих-пых!