Как устроены массивы (Array) в Swift?

Ответ

Массив (Array<Element>) в Swift — это упорядоченная коллекция элементов одного типа с нулевой индексацией. Это value type, реализующий copy-on-write для эффективности.

Ключевые характеристики:

  • Типизация: строгая, с поддержкой generics ([Int], [String])
  • Изменяемость: определяется объявлением (var — изменяемый, let — неизменяемый)
  • Динамический размер: автоматически увеличивается при добавлении элементов
  • Производительность: доступ по индексу — O(1), вставка в конец — амортизированная O(1)

Примеры:

// Создание и модификация
var numbers = [1, 2, 3]
numbers.append(4) // [1, 2, 3, 4]
numbers[0] = 10   // [10, 2, 3, 4]

// Неизменяемый массив
let colors = ["red", "green", "blue"]
// colors.append("yellow") // Ошибка компиляции

// Инициализация
var empty: [String] = []
var initialized = Array(repeating: 0, count: 5) // [0, 0, 0, 0, 0]

Оптимизация copy-on-write:

var a = [1, 2, 3]
var b = a          // Нет реального копирования, разделяют память
b.append(4)        // Только здесь создается копия для b
print(a)           // [1, 2, 3]
print(b)           // [1, 2, 3, 4]

Ответ 18+ 🔞

Э, слушай, смотри, вот этот твой массив в Swift — Array<Element>, ну, это типа как упорядоченная куча чего-то одного и того же, понимаешь? Элементы там под номерами, с нуля начинается. И главная фишка — это value type, блядь, но умный! Не тупо копирует всё сразу, а работает по принципу copy-on-write, то есть пока не начнёшь менять — память одну и ту же юзают. Хитро, да?

Что там у него по ключевым приколам:

  • Типы: Жёстко, сука. Не сунешь строку туда, где числа. Generics, всё дела — [Int], [String].
  • Менять можно или нет: А вот это от объявления зависит. Сказал var — царь и бог, меняй что хочешь. Сказал let — сиди и не дергайся, массив заморожен.
  • Размер: Динамический, ёпта! Сам растёт, когда ты в него что-то пихаешь. Не надо как в старых языках размер заранее объявлять.
  • Скорость: Доступ по индексу — мгновенный, O(1). Добавить в конец — в среднем тоже быстро, амортизированная O(1). Но если в середину лезешь — там уже может подзатормозить, это надо понимать.

Ну, примеры, чтобы не быть голословным:

// Создаём и колбасим
var numbers = [1, 2, 3]
numbers.append(4) // [1, 2, 3, 4]
numbers[0] = 10   // [10, 2, 3, 4] — взял и первый элемент переписал!

// А вот это уже священная корова, неизменяемый
let colors = ["red", "green", "blue"]
// colors.append("yellow") // Ошибка компиляции, блядь! Нельзя, сказал же let!

// Разные способы родить массив
var empty: [String] = [] // Просто пустой
var initialized = Array(repeating: 0, count: 5) // [0, 0, 0, 0, 0] — пять нулей, готово!

А вот про эту самую оптимизацию copy-on-write, это вообще песня:

var a = [1, 2, 3]
var b = a          // В этот момент, блядь, НЕТ КОПИРОВАНИЯ! Они как братья-близнецы, память одну делят.
b.append(4)        // А вот тут — ОПА! — `b` понимает, что надо меняться, и только СЕЙЧАС делает себе отдельную копию.
print(a)           // [1, 2, 3] — у `a` всё по-старому, его не ебёт.
print(b)           // [1, 2, 3, 4] — а `b` уже со своей четвёркой.

Вот такая магия, ебать мои старые костыли! Умно сделано, чтобы память зря не жрать.