Всегда ли экземпляр reference type (класса) размещается в куче (heap) в Swift?

«Всегда ли экземпляр reference type (класса) размещается в куче (heap) в Swift?» — вопрос из категории Управление памятью, который задают на 22% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Нет, не всегда. Хотя по умолчанию экземпляры классов (reference types) размещаются в куче, компилятор Swift может проводить оптимизации, которые меняют это поведение.

Основные исключения и оптимизации:

  1. Stack Promotion (продвижение в стек): Если компилятор может доказать, что время жизни объекта ограничено текущей областью видимости (например, локальный объект внутри функции, который никуда не передается), он может разместить его в стеке для повышения производительности.
    func processData() {
        class LocalProcessor { var data: Int = 0 }
        let processor = LocalProcessor() // Может быть оптимизирован и размещен в стеке
        // Использование processor
    } // Объект уничтожается здесь
  2. Оптимизация замыканий: Контекст (captured values) для не-escaping замыканий также может быть размещен в стеке.

Почему это важно? Размещение в стеке значительно быстрее (выделение/освобождение — это просто движение указателя стека), но возможно только при строгих условиях, гарантирующих короткое время жизни объекта. Для объектов, передаваемых между функциями, потоками или имеющих неопределенное время жизни, используется куча.