指針?lè)诸?lèi):
- raw pointer:未指定數(shù)據(jù)類(lèi)型的指針(原生指針)
- typed pointer:指定數(shù)據(jù)類(lèi)型的指針
表示方式:
raw pointer 在swift中的表示是UnsafeRawPointer
typed pointer在swift中的表示是UnsafePointer<T>,是一個(gè)泛型
Swift對(duì)照Objective-C,指針對(duì)應(yīng)的關(guān)系:
| Swift | Objective-C | 說(shuō)明 |
|---|---|---|
| UnsafePointer<T> | const T * | 指針和指向的內(nèi)容都是不可變的 |
| UnsafeMutablePointer<T> | T * | 指針和指向的內(nèi)容均是可變的 |
| UnsafeRawPointer | const void * | 指針指向未知的類(lèi)型 |
| UnsafeMutableRawPointer | void * | 指針指向尾椎的類(lèi)型(可以修改) |
原生指針的使用(RawPointer):
//指針內(nèi)存需要手動(dòng)管理
let p = UnsafeMutableRawPointer.allocate(byteCount: 32, alignment: 8)
for i in 0..<4 {
//advanced:步長(zhǎng)
//storebytes:寫(xiě)入內(nèi)存
p.advanced(by: i * 8).storeBytes(of: i, 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()
打印結(jié)果:
index0,value:0
index1,value:1
index2,value:2
index3,value:3
Program ended with exit code: 0
內(nèi)容補(bǔ)充:在看Swift源碼中查看UnsafeMutableRawPointer的過(guò)程中會(huì)有builtin
//builtin(標(biāo)準(zhǔn)模塊) -->在編譯的過(guò)程中會(huì)匹配LLVM里面的類(lèi)型和方法,在當(dāng)前編譯過(guò)程當(dāng)中,減少編譯時(shí)的內(nèi)存負(fù)擔(dān)
創(chuàng)建類(lèi)型指針:
方式一:
var age = 10
let p = withUnsafePointer(to: &age) { $0 }
方式二:
let ptr = UnsafeMutablePointer<Int>.allocate(capacity: 1)
ptr.initialize(to: age)
ptr.deinitialize(count: 1)
ptr.deallocate()
知識(shí)補(bǔ)充:?jiǎn)我槐磉_(dá)式
例子:
//ptr in return ptr :?jiǎn)我槐磉_(dá)式,可以直接使用ptr來(lái)表示,也可以直接使用$0來(lái)表示
//方式一:
{ ptr in return ptr }
方式二:
{ ptr }
方式三:
{ $0 }
創(chuàng)建泛型指針:
struct LGTeacher {
var age = 10
var height = 1.85
}
var t = LGTeacher()
let ptr = UnsafeMutablePointer<LGTeacher>.allocate(capacity: 2)
ptr.initialize(to: LGTeacher())
ptr.advanced(by: 1).initialize(to: LGTeacher(age: 20, height: 1.75))
print(ptr[0])
print(ptr[1])
print(ptr.pointee)
print((ptr + 1).pointee)
print(ptr.successor().pointee)
ptr.deinitialize(count: 2)
ptr.deallocate()
打印結(jié)果:
LGTeacher(age: 10, height: 1.85)
LGTeacher(age: 20, height: 1.75)
LGTeacher(age: 10, height: 1.85)
LGTeacher(age: 20, height: 1.75)
LGTeacher(age: 20, height: 1.75)
Program ended with exit code: 0
知識(shí)補(bǔ)充:successor()
print(ptr.successor().pointee) 與 print((ptr + 1).pointee) 結(jié)果是一致的,本質(zhì)上successor()這個(gè)方法就是向前移動(dòng)8字節(jié)
實(shí)戰(zhàn)一:將將變量t綁定到結(jié)構(gòu)圖HeapObject內(nèi)存中
思路:
1、獲取實(shí)例變量的內(nèi)存地址(指針)
2、RawPointer-->重新綁定到heapObject內(nèi)存指針
代碼實(shí)現(xiàn):
struct HeapObject {
var kind: UnsafeRawPointer
var strongRef: UInt32
var unownedRef: UInt32
}
class LGTeacher {
var age = 18
}
var t = LGTeacher()
//1、獲取實(shí)例變量的內(nèi)存地址(指針)
let ptr = Unmanaged.passUnretained(t as AnyObject).toOpaque()
//2、RawPointer-->重新綁定到heapObject內(nèi)存指針
let heapObject = ptr.bindMemory(to: HeapObject.self, capacity: 1)
print(heapObject.pointee)
輸出結(jié)果:
HeapObject(kind: 0x0000000100008168, strongRef: 3, unownedRef: 0)
Program ended with exit code: 0
知識(shí)補(bǔ)充:
1、Unmanaged:所有權(quán)的轉(zhuǎn)換
提供兩個(gè)方法:
passRetained(引用計(jì)數(shù)+1,獲取指針)
passUnretained(引用計(jì)數(shù)不+1,只獲取指針)
2、bindMemory:指針重定向
實(shí)戰(zhàn)二:將HeapObject中kind變量綁定到lg_swift_class
思路:
1、獲取實(shí)例變量的內(nèi)存地址(指針)
2、將指針重新綁定到lg_swift_class類(lèi)內(nèi)存指針
代碼:
struct HeapObject {
var kind: UnsafeRawPointer
var strongRef: UInt32
var unownedRef: UInt32
}
struct lg_swift_class {
var kind: UnsafeRawPointer
var superClass: UnsafeRawPointer
var cacheData1: UnsafeRawPointer
var cacheData2: UnsafeRawPointer
var data: UnsafeRawPointer
var falgs: UInt32
var instanceAddressOffset: UInt32
var instanceSize: UInt32
var finstanceAlignMaskags: UInt16
var reserved: UInt16
var classSize: UInt32
var classAddressOffset: UInt32
var description: UnsafeRawPointer
}
class LGTeacher {
var age = 18
}
var t = LGTeacher()
//1、獲取實(shí)例變量的內(nèi)存地址(指針)
let ptr = Unmanaged.passUnretained(t as AnyObject).toOpaque()
//2、RawPointer-->重新綁定到lg_swift_class內(nèi)存指針
let heapObject = ptr.bindMemory(to: HeapObject.self, capacity: 1)
let metaPtr = heapObject.pointee.kind.bindMemory(to: lg_swift_class.self, capacity: 1)
print(metaPtr.pointee)
輸出結(jié)果:
lg_swift_class(kind: 0x0000000100008140, superClass: 0x00007fff889888f8, cacheData1: 0x00007fff20206af0, cacheData2: 0x0000802000000000, data: 0x0000000100776562, falgs: 2, instanceAddressOffset: 0, instanceSize: 24, finstanceAlignMaskags: 7, reserved: 0, classSize: 136, classAddressOffset: 16, description: 0x0000000100003c3c)
Program ended with exit code: 0
說(shuō)明:
lg_swift_class(kind: 0x0000000100008140, superClass: 0x00007fff889888f8, cacheData1: 0x00007fff20206af0, cacheData2: 0x0000802000000000, data: 0x0000000100776562, falgs: 2, instanceAddressOffset: 0, instanceSize: 24, finstanceAlignMaskags: 7, reserved: 0, classSize: 136, classAddressOffset: 16, description: 0x0000000100003c3c)
按照打印出來(lái)的結(jié)果來(lái)看,顯示了具體內(nèi)存地址的大小,與給定的數(shù)據(jù)類(lèi)型相同
擴(kuò)展:xx類(lèi)指針怎么轉(zhuǎn)換成元類(lèi)指針,使用bindMemory,原理同上
實(shí)戰(zhàn)三:assumingMemoryBound的使用:如果將元組tuple數(shù)據(jù)傳遞給testPointer方法
思路:
將tuple類(lèi)型轉(zhuǎn)換成UnsafePointer,然后使用assumingMemoryBound假定內(nèi)存綁定,告訴編譯器不要再次進(jìn)行類(lèi)型檢查了
代碼:
var tuple = (10, 20)
func testPointer(_ p: UnsafePointer<Int>) {
print(p)
print("end")
}
//assumingMemoryBound:假定內(nèi)存綁定,告訴編譯器tulPtr已經(jīng)綁定過(guò)Int類(lèi)型了,現(xiàn)在tulptr就是Int類(lèi)型,不需要再次進(jìn)行編譯檢查了
withUnsafePointer(to: &tuple) { (tulPtr: UnsafePointer<(Int, Int)>) in
testPointer(UnsafeRawPointer(tulPtr).assumingMemoryBound(to: Int.self))
}
輸出結(jié)果:
0x0000000100008058
(lldb) x/8g 0x0000000100008058
0x100008058: 0x000000000000000a 0x0000000000000014
0x100008068: 0x0000000000000000 0x0000000000000000
0x100008078: 0x0000000000000000 0x0000000000000000
0x100008088: 0x0000000000000000 0x0000000000000000
(lldb)
根據(jù)格式化輸出內(nèi)存地址顯示,tuple已經(jīng)打印出來(lái)了,0xa是10,0x14是20
實(shí)戰(zhàn)四:assumingMemoryBound的使用:如何獲取結(jié)構(gòu)體類(lèi)型的指針
思路:
通過(guò)原生指針+偏移量的方式
代碼:
struct HeapObject {
var strongRef = 10
var unownedRef = 20
}
func testPointer(_ p: UnsafePointer<Int>) {
print(p)
print("end")
}
var t = HeapObject()
withUnsafePointer(to: &t) { (ptr: UnsafePointer<HeapObject>) in
//通過(guò)原生指針+內(nèi)存偏移來(lái)獲取
let strongRefPtr = UnsafeRawPointer(ptr) + MemoryLayout<HeapObject>.offset(of: \HeapObject.strongRef)!
testPointer(strongRefPtr.assumingMemoryBound(to: Int.self))
}
打印結(jié)果:
0x0000000100008078
(lldb) x/8g 0x0000000100008078
0x100008078: 0x000000000000000a 0x0000000000000014
0x100008088: 0x0000000100760680 0x0000000000000000
0x100008098: 0x0000000000000000 0x0000000000000000
0x1000080a8: 0x0000000000000000 0x0000000000000000
(lldb)
根據(jù)格式或內(nèi)存地址的結(jié)果說(shuō)明:strongRef = 0xa =10,unownedRef = 0x14 = 20
總結(jié):學(xué)習(xí)過(guò)程中一點(diǎn)積累,越來(lái)越好,加油