DevPrep

Все темы › Современный Swift

Что такое existential container (any P)? Почему any дороже, чем T: P?

Senior PRO

Суть

any P — значение неизвестного на компиляции типа, поэтому компилятор упаковывает его в existential container фиксированного размера:

Итого any P занимает 40 байт. Если значение влезает в буфер — лежит инлайн; если нет — аллоцируется в куче, а в буфере хранится ссылка (boxing). Класс-экземпляр всегда помещается: это одна ссылка. Для class-bound протокола (any P & AnyObject) контейнер короче: ссылка + witness table, 16 байт, metadata берётся из объекта.

protocol P {}
struct Small: P { var a, b, c: Int }        // 24 байта — помещается в буфер
struct Big: P { var a, b, c, d: Int }       // 32 байта — уедет в кучу (boxing)
final class Obj: P {}

print(MemoryLayout<Small>.size, MemoryLayout<Big>.size)   // 24 32
print(MemoryLayout<any P>.size)                            // 40
print(MemoryLayout<any P & AnyObject>.size)                // 16

let values: [any P] = [
    Small(a: 1, b: 2, c: 3), Big(a: 1, b: 2, c: 3, d: 4), Obj()
]

Продолжение ответа с кодом и уточняющими вопросами интервьюера — в приложении DevPrep.

Полный ответ — в DevPrep

Потренируйтесь перед собеседованием

В DevPrep эти ответы превращаются в задачи на минуту: что напечатает код, найди баг, пробное собеседование. По задаче в день.

Скачать DevPrep в App Store