Swift,字符串和内存地址

12

有一些关于Swift如何管理字符串的内存地址的问题我不太理解。

1. 引用类型

这里fooboo是指向同一内存位置的两个指针。

class Foo { }

let foo = Foo()
let boo = foo

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

好。

2. 值类型

let word0 = "hello"
let word1 = word0

现在,word0word1值类型,但这里涉及到写时复制机制。
[...] 然而,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是一个以某种方式符合AnyObjectstruct

已使用Xcode 7 GM Playground和Swift 2.0进行测试。


1
那么它们为什么有两个不同的内存地址呢?那么你为什么关心呢? - matt
5
当一个字符串被传递给期望 AnyObject 类型的函数时,它会自动地桥接到 NSObject。请参见我在 http://stackoverflow.com/questions/32637688/is-it-possible-to-mutate-a-string-in-swift-such-that-it-can-be-proven-to-modify 上的评论。实际上,在已编译项目中,word0/1 的输出相同,但在 Playground 中输出不同。 - Martin R
@matt 哈哈...:D 是的。我开始也这么想。但是这个问题https://dev59.com/vY_ea4cB1Zd3GeqPLDOL以及在我的答案下面激烈的评论交流促使我提出了这个问题。 - Luca Angeletti
1
这里有类似的观察结果:https://dev59.com/2ozda4cB1Zd3GeqPrM2n。我认为你不能假设自动桥接到 Foundation 对象每次都返回相同的实例。 - Martin R
@MartinR:明白了。非常感谢你。如果你想把你的评论写成答案,我会接受的。 - Luca Angeletti
2个回答

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

接受一个 AnyObject 参数,即一个 class 实例。它返回指向被 object 引用的对象所使用的存储的指针。

addressOf() 不能和 struct 变量一起使用。

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对象的内存位置指针。

似乎你不能做出任何关于在同一个Swift字符串上重复进行此桥接时是否返回相同的NSString对象(或更一般地说,相同的Foundation对象)的假设。即使在Playground中。

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

返回三个不同的地址(但在编译后的项目中是相同的地址)。在A different bridging between Array and Dictionary中也发现了相同的情况(对于数组和字典)。


那么我们如何将其应用于结构体呢?如果我想要一个自定义结构体的内存地址,真正的内存地址,零强制转换为基础类对象,我该怎么做? - karan satia

-1

Swift 3.0 Unmanaged.passUnretained(object).toOpaque()

Swift 3.0 Unmanaged.passUnretained(object).toOpaque()


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接