重学Swift第四篇:指针 & 内存管理

本文详细介绍了Swift中的指针类型,包括RawPointer和TypedPointer的使用,并深入探讨了Swift的内存管理机制,如引用计数、swift_retain和swift_release的实现。此外,还分析了解决循环引用的方法,包括弱引用和unowned引用的使用,以及在捕获列表中的应用。文章通过源码分析,揭示了Swift内存管理的底层细节。
摘要由CSDN通过智能技术生成

一、指针

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
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值