swift--指针与内存绑定

指针

Swift中的指针分为两类, typed pointer指定数据类型指针,raw pinter未指定数据类型的指针(原⽣指针)

raw pinter在Swift中的表示是 UnsafeRawPointer
typed pointer在Swift中的表示是 UnsafePointer

Swift Object-C 说明
unsafePointer const T * 指针及所指向的内容都不可变
unsafeMutablePointer T * 指针及其所指向的内存内容均可变
unsafeRawPointer const void * 指针指向未知类型
unsafeMutableRawPointer void * 指针指向未知类型

RawPointer使用

//指针的内存管理是手动管理
//申请32字节内存空间,8字节对齐方式
let p = UnsafeMutableRawPointer.allocate(byteCount: 32, alignment: 8)

for i in 0..<4 {
    //advanced 前进字节
    //storeBytes 储存数据
    p.advanced(by: i*8).storeBytes(of: i+1, as: Int.self)
}
for i in 0..<4 {
    //读取数据
    let value = p.load(fromByteOffset: i*8, as: Int.self)
    print("index\(i),value:\(value)")
}
p.deallocate()

allocate来开辟内存空间

 @inlinable
  public static func allocate(
    byteCount: Int, alignment: Int
  ) -> UnsafeMutableRawPointer {
    var alignment = alignment
    if alignment <= _minAllocationAlignment() {
      alignment = 0
    }
    return UnsafeMutableRawPointer(Builtin.allocRaw(
        byteCount._builtinWordValue, alignment._builtinWordValue))
  }

Builtin是LLVM标准模块。

unsafePointer

@inlinable public func withUnsafePointer(to value: T, _ body: (UnsafePointer) throws -> Result) rethrows -> Result

通过rethrows将结果向上级传递

var age = 10
let p = withUnsafePointer(to: &age) {
    //单一表达式可省略
    //ptr in return ptr
    $0
}
print(p.pointee)

p就是$0,代表UnsafePointer这个对象指针,p.pointee就是值

var age = 10
age = withUnsafePointer(to: &age) { ptr in
    return ptr.pointee + 12
}
print(age)
··········UnsafeMutablePointer
22

这个时候返回的就是闭包返回值。

UnsafeMutablePointer

var age = 10
withUnsafeMutablePointer(to: &age) { ptr in
    ptr.pointee += 10
}
print(p)

UnsafeMutablePointer的区别就是可以直接对原始对象进行修改。

struct Teacher {
    var age = 10
    var height = 1.85
}

var t = Teacher()

let ptr = UnsafeMutablePointer.allocate(capacity: 2)
ptr.initialize(to: Teacher())
ptr.advanced(by:1).initialize(to: Teacher(age: 18, height: 1.66))
print(ptr[0])
print(ptr[1])
print(ptr.successor().pointee)

//手动管理
ptr.deinitialize(count: 2)
ptr.deallocate()
··············
Teacher(age: 10, height: 1.85)
Teacher(age: 18, height: 1.66)
Teacher(age: 18, height: 1.66)

内存绑定

  • withMemoryRebound : 临时更改内存绑定类型
    -bindMemory(to: Capacity:) : 更改内存绑定的类型,如果之前没有绑定,那么就是⾸次绑定;如果绑 定过了,会被重新绑定为该类型。
  • assumingMemoryBound: 假定内存绑定,这⾥是告诉编译器:哥们我就是这种类型,你不要检查我 了。
withMemoryRebound

var age = 10
let ptr = withUnsafePointer(to: &age){$0}
ptr.withMemoryRebound(to: UInt64.self, capacity: 1) { (ptr: UnsafePointer) in
    print(ptr.pointee)
}
bindMemory

结合之前学过的


struct HeapObject {
    var kind: UnsafeRawPointer
    var strongref: UInt32
    var unownedRef:UInt32
}
struct _swift_class {
    var kind: UnsafeRawPointer
    var superClass: UnsafeRawPointer
    var cachedata1: UnsafeRawPointer
    var cachedata2: UnsafeRawPointer
    var data: UnsafeRawPointer
    var flags: UInt32
    var instanceAddressOffset: UInt32
    var instanceSize: UInt32
    var flinstanceAlignMask: UInt16
    var reserved: UInt16
    var classSize: UInt32
    var classAddressOffset: UInt32
    var description: UnsafeRawPointer
    
}
class Teacher {
    var age = 18
}
var t = Teacher()
//相当于OCheCF交互方式,__bridge 所有权转变,转为指针
//passUnretained非retain
let ptr = Unmanaged.passUnretained(t as AnyObject).toOpaque()
//bindMemory 重新绑定类型
let hep = ptr.bindMemory(to: HeapObject.self, capacity: 1)
let meta = hep.pointee.kind.bindMemory(to: _swift_class.self, capacity: 1)

print(meta.pointee)
···················
_swift_class(kind: 0x0000000100004140, superClass: 0x00007fff97884f98, cachedata1: 0x00007fff6c7cf3d0, cachedata2: 0x0000002000000000, data: 0x0000000101a0eed2, flags: 2, instanceAddressOffset: 0, instanceSize: 24, flinstanceAlignMask: 7, reserved: 0, classSize: 136, classAddressOffset: 16, description: 0x0000000100002be8)

这样我们就可以查看metadata.

assumingMemoryBound
var tul = (10,20)
func testPointer(_ p :UnsafePointer){
    print(p[0],p[1])
}
withUnsafePointer(to: &tul) {  (tulPtr : UnsafePointer<(Int,Int)>) in
    //assumingMemoryBound 假定类型 告诉编译器类型,不需要检查
    testPointer(UnsafeRawPointer(tulPtr).assumingMemoryBound(to: Int.self))
}
··············
10 20

直接获取地址。

内存绑定是不安全的,需要我们自己掌控

你可能感兴趣的:(swift--指针与内存绑定)