swift--指针与内存绑定

指针

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

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

Swift Object-C 说明
unsafePointer<T> 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<T, Result>(to value: T, _ body: (UnsafePointer<T>) 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<Teacher>.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<UInt64>) 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<Int>){
    print(p[0],p[1])
}
withUnsafePointer(to: &tul) {  (tulPtr : UnsafePointer<(Int,Int)>) in
    //assumingMemoryBound 假定类型 告诉编译器类型,不需要检查
    testPointer(UnsafeRawPointer(tulPtr).assumingMemoryBound(to: Int.self))
}
··············
10 20

直接获取地址。

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容