String
- очень сложный зверь.Он имеет много различных базовых представлений, в том числе:
Строковые литералы, которые хранятся в виде констант в двоичном виде
Небольшие строки, в которых можно хранитьдо 15 кодовых блоков UTF-8, встроенных в стек (по крайней мере, на x86)
«Собственные» строки (т. е. строки, которые не были соединены с Objective-C), которыехранятся в выделенном хвостом буфере кучи
«Внешние» строки из Obj-C, которые могут быть представлены теговым указателем или выделенной кучей NSString
объект
«Общие» строки, которые могут представлять строковый литерал Swift в виде выделенного в куче объекта Obj-C
Если вы хотите погрузиться в мелкие мелкие детали, вы можетеначните с StringObject.swift , в котором есть несколько комментариев, объясняющих некоторые детали макета.
Чтобы ответить на ваш вопрос о приведенных вами примерах:
let a = ""
Пустая строка имеет каноническую маленькую строку representation , которая хранится в стеке inline.
let b = "o"
Строковый литерал хранится в двоичном виде как константа.Следовательно, выделение кучи не требуется - указатель на адрес строки в двоичном файле - это все, что требуется.
Но даже если это не постоянная строка, например, она была создана:
let o = "O".lowercased()
Тогда он все еще может быть представлен в виде небольшой строки, которая хранится в стеке.
var str: String?
String
имеет дополнительного жителя (вминимум на x86), что означает, что String?
может использовать тот же макет, что и String
.Значение nil
представлено одним из битовых шаблонов дополнительных обитателей.
Но даже если String
не имеет дополнительного обитателя, дополнительное выделение кучи не потребуется для представления String?
над String
- для этого потребуется только дополнительный бит встроенного хранилища.