Быстрые, строковые и запоминающие адреса

Есть что-то, что я не понимаю о том, как Swift управляет адресом памяти String(s)

1. Типы ссылок

Здесь foo и boo - 2 указателя на ту же ячейку памяти.

class Foo { }

let foo = Foo()
let boo = foo

unsafeAddressOf(foo) // "UnsafePointer(0x7FCD13719BE0)"
unsafeAddressOf(boo) // "UnsafePointer(0x7FCD13719BE0)" 

Хорошо.

2. Типы значений

let word0 = "hello"
let word1 = word0

Теперь word0 и word1 являются value types, но здесь задействован механизм copy on write.

[...] Однако Swift выполняет только фактическую копию за кулисами, когда это абсолютно необходимо сделать. Swift управляет копированием всех значений, чтобы обеспечить оптимальную производительность, и вам не следует избегать назначения, чтобы попытаться устранить эту оптимизацию. https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html#//apple_ref/doc/uid/TP40014097-CH13-XID_134

Итак, почему у них есть два разных адреса памяти?

unsafeAddressOf(word0) // "UnsafePointer(0x7FCD1342ACE0)"
unsafeAddressOf(word1) // "UnsafePointer(0x7FCD13414260)"

3. Подробнее

Также обратите внимание, что String является struct, который как-то соответствует до AnyObject.

Протестировано игровой площадкой Xcode 7 GM и Swift 2.0.

Ответ 1

func unsafeAddressOf(object: AnyObject) -> UnsafePointer<Void>

принимает параметр AnyObject, то есть экземпляр класса. Он возвращает указатель на хранилище, используемое для указанного объекта на object.

addressOf() не может использоваться со структурными переменными:

struct Foo { }
var f = Foo()
let a = unsafeAddressOf(f)
// error: cannot invoke 'unsafeAddressOf' with an argument list of type '(Foo)'

String является struct, однако он автоматически привязан к NSString при передаче функции, ожидающей объект. Итак,

let word0 = "hello"
let p1 = unsafeAddressOf(word0)

фактически выполняет

let p1 = unsafeAddressOf(word0 as NSString)

Вы не получаете адрес переменной word0, но указатель на памяти объекта с мостиком NSString.

Похоже, вы не можете делать никаких предположений о том, является ли этот мост возвращает идентичный объект NSString (или, в более общем плане, тот же Объект Foundation), когда выполняется многократно в одной строке Swift. На игровой площадке даже

let word0 = "hello"
let p1 = unsafeAddressOf(word0)
let p2 = unsafeAddressOf(word0)
let p3 = unsafeAddressOf(word0)

возвращает три разных адреса (но те же адреса в скомпилированном проект). Это же наблюдение (для массивов и словарей) было сделано в Разный мост между Array и Dictionary.

Ответ 2

Swift 3.0 Unmanaged.passUnretained(объект).toOpaque()