Как определяется объём памяти, занимаемый value type (структурой, enum) в Swift?

«Как определяется объём памяти, занимаемый value type (структурой, enum) в Swift?» — вопрос из категории Управление памятью, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Value type (структура, перечисление, кортеж) хранится непосредственно в том контексте, где он объявлен (стек, другая структура и т.д.), и занимает ровно столько памяти, сколько требуется для хранения всех его полей, с учётом выравнивания (alignment).

1. Расчёт размера: Используйте MemoryLayout<T> для статического определения размера.

struct Point {
    let x: Double // 8 байт
    let y: Double // 8 байт
}

print(MemoryLayout<Point>.size)     // 16 (фактический размер данных)
print(MemoryLayout<Point>.stride)   // 16 (размер с учётом выравнивания)
print(MemoryLayout<Point>.alignment) // 8 (требуемое выравнивание)

2. Размеры примитивных типов (64-bit):

  • Int, UInt, Double: 8 байт
  • Float, Int32: 4 байта
  • Bool: 1 байт
  • Character: 16 байт (из-за поддержки Unicode)

3. Ключевые особенности:

  • Copy-on-Write (COW): Для оптимизации такие типы, как String, Array, Dictionary, Set, хотя и являются value type, хранят свои буферы в куче. Копирование происходит только при модификации, что экономит память.
  • Выравнивание: Компилятор может добавлять паддинг (padding) между полями для соблюдения alignment, что увеличивает stride. Например, структура с Bool (1 байт) и Int (8 байт) займёт не 9, а 16 байт из-за выравнивания Int на границу 8 байт.

Правило: Размер value type предсказуем и равен сумме размеров его членов + padding.