Ответ
Основное место хранения — куча (heap). String в Swift — это тип-значение с семантикой Copy-on-Write (CoW).
Принцип Copy-on-Write: Несколько переменных могут указывать на один буфер в памяти, пока строки не изменяются. Копирование происходит только при модификации.
var original = "Hello" // Буфер создается в куче.
var copy = original // Копирования НЕТ. Обе переменные ссылаются на один буфер.
copy.append(", World!") // ТЕПЕРЬ создается отдельная копия буфера для `copy`.
print(original) // "Hello" (не изменилась)
Оптимизации:
- Small String Optimization (SSO): Строки длиной до 15 UTF-8 символов (на 64-битных платформах) могут храниться непосредственно в самом значении
String(в стеке для локальных переменных), без выделения памяти в куче. - Эффективное копирование: Благодаря CoW присваивание строк выполняется за O(1).
Практический вывод:
- Не нужно бояться передачи или возврата
Stringиз-за производительности. - Для частых модификаций больших строк используйте
var. - Для строк-констант предпочтительнее
let, чтобы компилятор мог применить дополнительные оптимизации.
Ответ 18+ 🔞
Ну вот, опять про эти ваши строки, блядь. Сидишь такой, думаешь: "О, строка, привет, как дела?" А она тебе — раз! — и в кучу, сука. Да, String в Swift — это тип-значение, но не обольщайся, чувак. Внутри у неё, блядь, мозги набекрень, система Copy-on-Write, или, как я это называю, "не трожь — не ебёт".
Суть этой хуйни (Copy-on-Write): Представь, у тебя есть одна строка. Ты её скопировал в другую переменную. Ты думаешь: "Всё, пиздец, память кончилась, сейчас две копии по куче болтаться будут!" А нихуя! Пока вы обе, как две мартышлюшки, просто смотрите на данные и не трогаете — вы делите один буфер в памяти. Как только одна из вас, хитрая жопа, решает что-то поменять — БАЦ! — вот тут-то и происходит настоящее копирование. Каждая получает свой личный буфер, чтобы не мешать друг другу.
var original = "Hello" // Буфер создаётся где? Правильно, в куче, блядь (если не повезло с SSO).
var copy = original // Копирования НЕТ, ёпта! Просто две ссылки на один и тот же адрес.
copy.append(", World!") // А вот тут, сука, тревога! `copy` решила пошалить. ТЕПЕРЬ создаётся её личная копия.
print(original) // "Hello" (у original свой мир, она не изменилась, всё чики-пуки)
А ещё у них там оптимизации, чтоб им не сдобровать:
- Small String Optimization (SSO): Это вообще шедевр, блядь. Если строка короткая (до 15 символов в UTF-8 на 64-битах), то ей насрать на кучу. Она вся помещается прямо внутри самого значения
String, как в чемоданчик. Никакого лишнего выделения, скорость — огонь. - Копирование — раз плюнуть: Из-за CoW просто скопировать ссылку — дело O(1). Быстро, как хуй с горы.
Так что же делать-то, мудя?
- Не пизди про производительность, когда передаёшь или возвращаешь
String. Компилятор и так всё оптимизирует, если ты, конечно, не начинаешь её в цикле наизнанку выворачивать. - Если собрался строку активно пилить-строгать — объявляй
var, не будь идиотом. - А если строка как скала — константа — ставь
letи спи спокойно. Компилятор это любит и может ещё какую-нибудь подлянку-оптимизацию подсунуть.