文章目录
一、指针
Swift的指针分为两类:
Raw Pointer
,未指定数据类型的指针,用UnsafeRawPointer
表示Typed Pointer
,指定数据类型的指针,用UnsafePointer< T >
表示
1.1 指针的使用
- 手动管理
//Raw Pointer
//通过allocate分配内存空间
let p = UnsafeMutableRawPointer.allocate(byteCount: 32, alignment: 8)
for i in 0..<4 {
//advanced按步长前进,storeBytes按字节存储
p.advanced(by: i * 8).storeBytes(of: i, as: Int.self)
}
for i in 0..<4 {
//load通过步长偏移按字节加载数据
let value = p.load(fromByteOffset: i * 8, as: Int.self)
print("index \(i) value \(value)")
}
p.deallocate() //手动销毁内存空间
//Typed Pointer
let p1 = UnsafeMutablePointer<Int>.allocate(capacity: 4)
for i in 0..<4 {
// (p1+i).initialize(to: i)
//advanced的by中的值会调用_builtinWordValue,typedPointer应该有内置的数据,所以传i就可以了
p1.advanced(by: i).initialize(to: i)
}
for i in 0..<4 {
// let value = p1[i]
let value = p1.advanced(by: i).pointee
print("index \(i) value \(value)")
}
p1.deinitialize(count: 4)
p1.deallocate()
- 自动管理及内存绑定
struct GCHeapMetadata {
var kind: UnsafeRawPointer
var superClass: UnsafeRawPointer
var cacheData1: UnsafeRawPointer
var cacheData2: UnsafeRawPointer
var data: UnsafeRawPointer
var flags: UInt32
var instanceAddressPoint: UInt32
var instanceSize: UInt32
var instanceAlignMask: UInt16
var reserved: UInt16
var classSize: UInt32
var classAddressPointer: UInt32
var description: UnsafeRawPointer
}
struct GCHeapObject {
var metadata: UnsafeRawPointer
var refCount: UInt64
}
class Test {
var a = 10
}
var test = Test()
//通过Unmanaged来自动管理, passUnretained返回一个Unmanaged,toOpaque()返回不透明指针
let ptr = Unmanaged<Test>.passUnretained(test).toOpaque()
//bindMemory将内存绑定到指定的类型,并返回指向绑定内存的类型化指针。
let heapObject = ptr.bindMemory(to: GCHeapObject.self, capacity: 1)
print(heapObject.pointee)
let metadata = heapObject.pointee.metadata.bindMemory(to: GCHeapMetadata.self, capacity: 1)
print(metadata.pointee)
- 访问结构体变量
struct Test {
var a = 10
var b = 20
}
var test = Test()
withUnsafePointer(to: &test) {
(ptr: UnsafePointer<Test>) in
//计算b在Test中的偏移,offset的参数为keypath
guard let offsetB = MemoryLayout<Test>.offset(of: \Test.b) else {
return
}
//通过Test的首地址 + offsetB拿到b的内存地址
let bPtr = UnsafeRawPointer(ptr) + offsetB
//告诉编译器假定内存绑定为Int类型
let intBPtr = bPtr.assumingMemoryBound(to: Int.self)
print(b.pointee) //打印20
}
内存绑定相关函数:
withMemoryRebound
:临时更改内存绑定类型bindMemory
:更改内存绑定类型,如果内存未绑定过,进行绑定。assumingMemoryBound
:假定内存绑定到指定类型。内存需已绑定过。
二、内存管理
Swift中也是采用ARC(Automatic Reference Counting,自动引用计数)来管理内存。
2.1 引用计数结构
在第一篇介绍HeapObjec结构体时简单提到成员变量InlineRefCounts refCounts
typedef RefCounts<InlineRefCountBits> InlineRefCounts;
template <typename RefCountBits>
class RefCounts {
std::atomic<RefCountBits> refCounts;
......
// Refcount of a new object is 1.
constexpr RefCounts(Initialized_t)
: refCounts(RefCountBits(0, 1