指针
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
直接获取地址。
内存绑定是不安全的,需要我们自己掌控