Как работает copy-on-write для строк в Swift?

«Как работает copy-on-write для строк в Swift?» — вопрос из категории Swift Core, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Copy-on-write (CoW) — это оптимизация, при которой копирование данных откладывается до момента фактической модификации. В Swift строки (тип String) реализуют этот механизм.

Как это работает:

  1. При присваивании строки другой переменной создается только новая ссылка на те же данные
  2. Фактическое копирование буфера памяти происходит только при попытке изменить одну из копий

Пример:

var original = "Hello, World!"
var copy = original // Нет копирования, обе переменные ссылаются на один буфер

print(original == copy) // true

// Проверим, что это одна и та же память (условно)
print(CFGetRetainCount(original as CFString)) // Увеличится счетчик ссылок

copy.append("!") // ТЕПЕРЬ происходит копирование!
// original и copy теперь имеют разные буферы в памяти

print(original) // "Hello, World!"
print(copy)     // "Hello, World!!"

Реализация CoW для пользовательских структур:

struct MyCoWStruct {
    private class Ref<T> {
        var value: T
        init(_ value: T) { self.value = value }
    }

    private var ref: Ref<[Int]>

    init(values: [Int]) {
        ref = Ref(values)
    }

    var values: [Int] {
        get { return ref.value }
        set {
            // Проверяем, единственная ли это ссылка
            if !isKnownUniquelyReferenced(&ref) {
                ref = Ref(newValue) // Копируем при модификации
                return
            }
            ref.value = newValue
        }
    }
}

var a = MyCoWStruct(values: [1, 2, 3])
var b = a // Нет копирования
b.values.append(4) // Происходит копирование, так как b изменяется

Важные особенности:

  • CoW работает только для типов-значений (struct, enum)
  • Компилятор Swift автоматически применяет CoW для стандартных коллекций (Array, Dictionary, Set) и строк
  • Для кастомных структур нужно реализовывать CoW вручную
  • Механизм не гарантирован для очень маленьких структур, где копирование дешевле проверки уникальности ссылки

Преимущества:

  • Экономия памяти при частом копировании
  • Быстрое присваивание без накладных расходов
  • Прозрачность для разработчика (работает автоматически)