UnsafeRawPointer assumeMemoryBound vs. bindMemory

sim*_*one 11 memory pointers swift

任何人都可以解释UnsafeRawPointer.assumimgMemoryBound(to:)和之间的区别是什么UnsafeRawPointer.bindMemory(to:capacity:)

编译或运行时差的一个实际例子将更受欢迎.

Swift DocbindMemory(to:capacity:):

此API允许内存区域在程序中的不同点保存不相关的类型.将未初始化的内存绑定到类型会使内存准备存储该类型的值.已初始化的绑定内存将内存中的值重新解释为新类型.如果旧值非常重要(需要销毁)或者在被覆盖之前从内存中读取它们,则新类型必须与旧类型相互布局兼容.

是什么意思将未初始化的内存绑定到类型准备内存来存储该类型的值?它分配了字节,对吧?那么bindMemory(to:capacity:)完成后有什么不同?

Ham*_*ish 14

Swift中分配的内存可以是:

  • 未初始化的原始内存
  • 未初始化的内存绑定到某个类型
  • 初始化内存绑定到一个类型

当您分配内存时UnsafeMutableRawPointer.allocate(bytes:alignedTo:),您将获得未初始化的原始内存.

使用时分配内存时UnsafeMutablePointer<T>.allocate(capacity:),会得到与该类型绑定的未初始化内存T.

  • bindMemory(to:capacity:)(重新)将指针的内存绑定到一个新类型,并返回一个类型指针来访问它.它可以在任何上述状态的指向内存的指针上调用; 虽然如果内存初始化,新绑定类型必须与旧绑定类型布局兼容,并且这两种类型应该是微不足道的.

    请注意,此方法执行分配或初始化; 它只是改变了内存的绑定类型.

  • assumingMemoryBound(to:)是一种从已知的原始指针获取类型指针的方法,该指针指向绑定到给定类型的内存.如果内存未绑定到此类型,则通过您返回的类型指针访问内存是未定义的行为.

这里需要注意的一件重要事情是,内存只能在给定时间绑定到一种类型.您可以自由重新绑定到其他类型(具有上述初始化内存的限制); 但是,尝试访问绑定到给定类型的内存作为无关类型会违反严格别名,因此是未定义的行为.

另一件需要注意的是,相关类型和布局兼容类型是独立的概念:

  • 如果绑定到类型的内存可以按位重新解释为具有类型,则类型T是与类型兼容布局.请注意,这不一定是双向关系.例如,布局是否兼容,如果一个'实例' 可以重新解释为2 x .反过来不可能是真的; 你不能从一个单一的价值形成.UUTInt(Int, Int)(Int, Int)Int(Int, Int)Int

  • 如果您可以将重叠内存与这些类型别名,则两种类型相关.例如,如果您有一个UnsafePointer<T>和一个UnsafePointer<U>,if TU不相关的类型,那么它们就不能指向彼此重叠的内存.

但是,我不相信Swift已经正式定义了这些术语的任何规则(我希望这将具有ABI稳定性).

那么bindMemory(to:capacity:)完成后有什么不同?

目前,没什么.正如安德鲁特里克马丁所链接的邮件列表讨论中所说:

绑定内存与编译器通信,内存位置对于类型化访问是安全的.在运行时没有任何事情发生 - 直到有人写了类型安全消毒剂.它影响内存位置的抽象状态,与用于访问该内存的指针变量无关.绑定内存返回一个类型指针,以方便和清晰,但没有什么特别的指针值.

有关此主题的进一步阅读,请参阅SE-0107内存模型说明部分,以及Swift中严格别名的非官方指南.