Как реализовать свой массив в Swift?
Что проверяют
Понимаете ли вы, как устроен стандартный Array: семантика значения, copy-on-write, амортизированная вставка и протоколы коллекций. Следом обычно спрашивают, что произойдёт при var b = a; b.append(1) в вашей реализации и почему.
Как отвечать
Начните с того, что Array в Swift это структура, которая держит ссылку на буфер в куче. Своя реализация повторяет эту схему:
- хранилище: класс-буфер на
ManagedBufferили наUnsafeMutablePointer<Element>с полямиcountиcapacity. Память выделяется черезallocate(capacity:), элементы создаютсяinitialize(to:), а передdeallocate()обязательно вызываетсяdeinitialize(count:); - обёртка:
struct MyArray<Element>, внутри ссылка на буфер. Снаружи тип ведёт себя как значение; - copy-on-write: перед любой мутацией проверка
isKnownUniquelyReferenced(&buffer). Если буфер разделён с другой копией, сначала копируем его, потом меняем; - рост: при нехватке места ёмкость удваивается. Тогда
appendстоит O(1) амортизированно, а не O(n) на каждый вызов; - протоколы: минимум для
CollectionэтоstartIndex,endIndex,subscriptиindex(after:). После этого бесплатно появляютсяfor-in,map,filter,firstи срезы.RandomAccessCollectionобещает доступ по индексу за O(1),RangeReplaceableCollectionчерезinit()иreplaceSubrange(_:with:)даётappend,insertиremove(at:), аExpressibleByArrayLiteralпозволяет писать литерал.
Выход за границы в стандартной библиотеке останавливает программу через precondition, а не возвращает nil. Свою реализацию делайте так же.
Где спотыкаются
Делают class CustomArray со стандартным массивом внутри. Это обёртка над готовым типом, да ещё с семантикой ссылки: две переменные меняют один объект, а интервьюер спрашивал именно про устройство.
Забывают проверку уникальности буфера. Копия структуры и оригинал продолжают писать в одну память, и изменение «копии» портит исходный массив.
Растят буфер на один элемент или не вызывают deinitialize перед освобождением. В первом случае заполнение массива становится квадратичным, во втором утекают объекты, на которые ссылались элементы.