## Value and Reference Types

|[Value Types](/5%20Swift/5.3%20DataRepresentations/5.3.1%20DataTypes/5.3.1.4%20ValueTypes/) (хранятся в [стеке](/3%20Memory%20and%20Concurrency/3.1%20Memory/3.1.2%20RandomAccessMemory/3.1.2.2%20Stack.md)) | [Reference Types](/5%20Swift/5.3%20DataRepresentations/5.3.1%20DataTypes/5.3.1.3%20ReferenceTypes/) (хранятся в [куче](/3%20Memory%20and%20Concurrency/3.1%20Memory/3.1.2%20RandomAccessMemory/3.1.2.3%20Heap.md))|
|------------|------------|
| Основные типы данных: Int, Bool, Char | Closure |
| [Struct](/5%20Swift/5.3%20DataRepresentations/5.3.1%20DataTypes/5.3.1.4%20ValueTypes/5.3.1.4.2%20Struct.md) | [Class](/5%20Swift/5.3%20DataRepresentations/5.3.1%20DataTypes/5.3.1.3%20ReferenceTypes/Class/Class.md)|
| Enum | [Function](/2%20ComputerScience/2.2%20Languages/2.2.2%20Paradigm/2.2.2.1%20Declarative/2.2.2.1.1%20FunctionalProgramming(FP).md) |
| Float, Double | |
| [Tuple](/5%20Swift/5.3%20DataRepresentations/5.3.1%20DataTypes/5.3.1.4%20ValueTypes/5.3.1.4.4%20CollectionsAndTuple/5.3.1.4.4.3%20Tuple.md) | |
| [Collections](/5%20Swift/5.3%20DataRepresentations/5.3.1%20DataTypes/5.3.1.4%20ValueTypes/5.3.1.4.4%20CollectionsAndTuple/5.3.1.4.4.1%20Collections.md): [Set](/5%20Swift/5.3%20DataRepresentations/5.3.1%20DataTypes/5.3.1.4%20ValueTypes/5.3.1.4.4%20CollectionsAndTuple/5.3.1.4.4.2%20AssociatedArray.md), String, Array, [Dictionary](/5%20Swift/5.3%20DataRepresentations/5.3.1%20DataTypes/5.3.1.4%20ValueTypes/5.3.1.4.4%20CollectionsAndTuple/5.3.1.4.4.2%20AssociatedArray.md) | |

### Компилятор Swift может упаковывать **value типы** или [протоколы](/5%20Swift/5.4%20Protocol/5.4.1%20Protocol.md) и [generic](/5%20Swift/5.5%20AbstractMechanism/5.5.1%20Generics.md), размещая их в [куче](/3%20Memory%20and%20Concurrency/3.1%20Memory/3.1.2%20RandomAccessMemory/3.1.2.3%20Heap.md):

1) При соблюдении [протокола](/5%20Swift/5.4%20Protocol/5.4.1%20Protocol.md). Помимо затрат на выделение ресурсов, возникают дополнительные накладные расходы, когда тип значения хранится в [экзистенциальном контейнере](/5%20Swift/5.5%20AbstractMechanism/5.5.3%20ExistentialTypes.md)
2) При смешивании value и reference типов.
3) [Generic](/5%20Swift/5.5%20AbstractMechanism/5.5.1%20Generics.md) с value типом:

```swift
struct Bas<T> {
    var x: T
    init(xx: T) {  
        x = xx
    }
}
```

4) Без [capture list](/3%20Memory%20and%20Concurrency/3.1%20Memory/3.1.3%20ReferenceCounting/3.1.3.1%20RefCountIniOS/3.1.3.1.4%20CaptureList/) происходит [захватывание](https://shantaram-kokate-swift.medium.com/capture-list-in-swift-a7d7d1328c84) value type как [strong ссылку](/3%20Memory%20and%20Concurrency/3.1%20Memory/3.1.3%20ReferenceCounting/3.1.3.1%20RefCountIniOS/3.1.3.1.4%20CaptureList/3.1.3.1.4.2%20Strong.md). И наоборот, с `[variable] in`([capture list](/3%20Memory%20and%20Concurrency/3.1%20Memory/3.1.3%20ReferenceCounting/3.1.3.1%20RefCountIniOS/3.1.3.1.4%20CaptureList/)) создается копия (локальная переменная) внутри замыкании.
5) Если от значения не требуется ссылка на местоположение (например, получение ссылки на структуру с помощью &), структура может быть расположена полностью в регистрах: при работе с небольшими структурами ее члены могут быть размещены в регистрах процессора, так что она даже не живет в памяти. (Это особенно актуально для небольших, возможно, недолговечных типов значений, таких как `Ints` и `Doubles`, которые гарантированно помещаются в регистры). [Ссылка](https://stackoverflow.com/questions/71071416/stack-and-heap-misunderstanding-in-swift)
6) Большие типы значений действительно выделяются в [heap](/3%20Memory%20and%20Concurrency/3.1%20Memory/3.1.2%20RandomAccessMemory/3.1.2.3%20Heap.md): хотя это деталь реализации Swift, которая теоретически может измениться в будущем, структуры, размер которых превышает 3 машинных слова (например, больше 12 байт на 32-битной машине или 24 байт на 64-битной машине), практически гарантированно будут выделены и сохранены в куче. Это не противоречит ценности типа значения: его по-прежнему можно произвольно копировать по желанию компилятора, и компилятор делает очень хорошую работу, чтобы избежать ненужных выделений там, где это возможно.

> Если размер вашего типа значения не может быть определен во время компиляции, или если ваш тип значения рекурсивно содержит/содержится ссылочным типом.

### Компилятор Swift может [продвигать](https://github.com/apple/swift/blob/62ccf81f7748e3e2c8626354d1ecb3adbd26b063/lib/SILOptimizer/Transforms/StackPromotion.cpp) **reference типы** для размещения в [стеке](//3%20Memory%20and%20Concurrency/3.1%20Memory/3.1.2%20RandomAccessMemory/3.1.2.2%20Stack.md):

1) Когда их размер фиксирован;
2) Когда время жизни может быть предсказано;

> Если размер вашего типа значения может быть определен во время компиляции, или если ваш тип значения не содержит рекурсию / не содержится ссылочным типом

Эта оптимизация происходит на этапе генерации [SIL](https://github.com/apple/swift/blob/main/docs/SIL.rst) в [Swift](/5%20Swift/5.1%20Swift.md)

![TypesOfFiles](/pictures/ComputerScience/TypesOfFiles.jpg?raw=true)


### Пример хранения данных структуры и класса

#### 1) Класс в классе

```swift
class ClassLocation {
    var name: String
    var point: ClassPoint
}
```

    ┌──────────────────────┐      ┌────────────────┐
    │       Location       │ ┌───▶│   ClassPoint   │
    ├──────────┬───────────┤ │    ├────────┬───────┤
    │   name   │   point ──┼─┘    │   x    │   y   │
    └──────────┴───────────┘      └────────┴───────┘

#### 2) Структура в классе 

```swift
class ClassLocation {
    var name: String
    var point: StructPoint
}
```

    ┌────────────────────────────┐
    │       ClassLocation        │
    ├──────────┬─────────────────┤
    │          │   StructPoint   │
    │   name   ├────────┬────────┤
    │          │  x     │  y     │
    └──────────┴────────┴────────┘

---

[5.3.1 Data Types Theme Folder](../5.3.1%20DataTypes/) | [Back To iTWiki Contents](https://github.com/eldaroid/iTWiki) | [5.3.1.2 Class vs Struct](./5.3.1.2%20ClassvsStruct.md)
