Ответ
Да, могут. Хотя value-типы по умолчанию размещаются в стеке, существует несколько сценариев, при которых они попадают в кучу:
- Когда value-тип является свойством класса. Классы — reference-типы, их экземпляры всегда размещаются в куче, а значит, и все их свойства (включая структуры и перечисления) хранятся там же.
- Когда value-тип захвачен escaping-замыканием. Если замыкание, захватившее value-тип, само сохраняется в куче (например, передано в асинхронную задачу), то захваченные значения также будут размещены в куче.
- При использовании unsafe-операций (например,
withUnsafeMutablePointer), которые могут явно работать с памятью в куче.
Пример:
class Container {
var storedStruct: MyStruct // Хранится в куче, так как является свойством класса
}
struct MyStruct {
var value: Int
}
let container = Container()
container.storedStruct = MyStruct(value: 42) // Экземпляр MyStruct теперь находится в куче
Почему это важно: Понимание этого механизма помогает избежать неверных предположений о производительности и предсказать поведение при работе с замыканиями и классами.
Ответ 18+ 🔞
А, ну это, блядь, классика! Все эти умники с порога заявляют: "Структуры — в стеке, классы — в куче, и точка, ёпта!" А потом такой выходит на сцену, блядь, Герасим-свистопердец и говорит: "Му-му". То есть нихуя не так, блядь!
Да, могут, сука. Хоть по дефолту эти value-типы и юзают стек, как нормальные пацаны, жизнь, блядь, вносит свои коррективы, в рот меня чих-пых. Вот тебе три пиздёжных сценария, когда твоя структурка отправится в эту самую кучу, как последняя мартышлюшка:
- Когда она — свойство какого-нибудь класса. Классы — это же reference-типы, ёпта, их экземпляры всегда сидят в куче, как в тюрьме. А раз так, то и всё их барахло, включая твои любимые структуры, болтается там же. Принцип "кто с кем ебётся, тот от того и сосёт" в действии, блядь.
- Когда её, дуру, захватило escaping-замыкание. Если замыкание, которое ухватило твою структурку за жопу, само сбежало в кучу (например, его отправили в асинхронную задачу), то и захваченные значения потащат за собой, волоком. Ничего не попишешь.
- При использовании unsafe-операций. Ну это уже для полных долбоёбов, которые играются с
withUnsafeMutablePointerи прочей чёрной магией, явно указывая памяти, где ей лежать. Тут уж сам напросился, блядь.
Смотри, как это выглядит на практике, ёбана:
class Container {
var storedStruct: MyStruct // Эта структурка уже обречена на кучу, ибо свойство класса. Пиздец ей.
}
struct MyStruct {
var value: Int
}
let container = Container()
container.storedStruct = MyStruct(value: 42) // Всё, приехали. Экземпляр MyStruct теперь не в стеке, а в этой самой куче, блядь.
А нахуй это знать-то? А затем, чувак, чтобы не быть тем самым мудаком, который думает, что раз он везде юзает struct, то у него летающая производительность. А потом херак — и всё тормозит, потому что структуры понабежали в кучу, как тараканы на пельмени. Предсказывать поведение, понимать, где что лежит, и не обосраться с замыканиями и классами — вот в чём, блядь, сила.