• Swift中使用内存指针手动管理内存
  • 发布于 2个月前
  • 218 热度
    0 评论
  • 远行de风
  • 0 粉丝 26 篇博客
  •   
前言
Swift 中的内存管理基于自动引用计数 (ARC),一般来说不需要我们手动操作内存。但是,除了 ARC 之外,Swift 还支持手动内存管理,这就需要手动操作内存指针了,今天就来讲讲这块儿内容。

swift 中的指针
操作内存指针被苹果认为是不安全的,且不推荐直接操作,因此关于指针的类型基本都是以 UnSafe 开头的,比如:
UnsafePointer
UnsafeMutablePointer
UnsafeBufferPointer
UnsafeMutableBufferPointer
UnsafeRawPointer
UnsafeMutableRawPointer
UnsafeRawBufferPointer
UnsafeMutableRawBufferPointer
接下来我们详细解释一下这些指针的用法。

UnsafePointer<T>
UnsafePointer<T>是一个指向类型 T 的不可变指针。它用于访问和操作内存中的数据,但不能修改数据本身,所以初始化的时候只能通过直接向它传递一个已经初始化的对象来进行。

读取指针指向的值只需要使用 pointee 属性
var array: [Int] = [1, 2, 3, 4, 5] // 堆代码 duidaima.com
let pointer = UnsafePointer<[Int]>(&array)
print(pointer.pointee) // 打印 [1, 2, 3, 4, 5]

UnsafeMutablePointer<T>
UnsafeMutablePointer<T>是一个指向类型 T 的可变指针。它用于访问和修改内存中的数据,和 UnsafePointer 的区别是可以修改。
var value = 10
let pointer = UnsafeMutablePointer<Int>(&value)

pointer.pointee = 20
print(value) // 打印 20

UnsafeBufferPointer<T>
UnsafeBufferPointer<T>是一个用于访问连续内存块中元素的不可变指针。它提供了对内存块的访问和遍历,因为 UnsafeBufferPointer 实现了 Collection,所以可以使用 forEach 等高阶函数。
var array: [Int] = [1, 2, 3, 4, 5]
let bufferPointer = UnsafeBufferPointer(start: array, count: array.count)

bufferPointer.forEach { value in
    print(value)
}

UnsafeMutableBufferPointer<T>
UnsafeMutableBufferPointer<T>是一个用于访问连续内存块中元素的可变指针。它提供了对内存块的访问和修改,与 UnsafeBufferPointer 不同的是,它可以修改。
var array: [Int] = [1, 2, 3, 4, 5]
let bufferPointer = UnsafeMutableBufferPointer(start: &array, count: array.count)

for i in bufferPointer.startIndex..<bufferPointer.endIndex {
    bufferPointer[i] += 1
}

print(array) // 打印 [2, 3, 4, 5, 6]

UnsafeRawPointer
UnsafeRawPointer 是一个指向原始内存的不可变指针。它可以用于访问和操作任意类型的内存数据。
var value = 10
let pointer = UnsafeRawPointer(&value)

let intValue = pointer.load(as: Int.self)
print(intValue) // 打印 10

UnsafeMutableRawPointer
UnsafeMutableRawPointer 是一个指向原始内存的可变指针。它可以用于访问和操作任意类型的内存数据。申请内存的时候可以指定大小和对齐方式:
let size = MemoryLayout<Int>.size
let alignment = MemoryLayout<Int>.alignment
let pointer = UnsafeMutableRawPointer.allocate(byteCount: 8, alignment: alignment)
pointer.storeBytes(of: 32, as: Int.self)
let value = pointer.load(as: Int.self)
print(value) // 打印 32

解释下代码:
首先使用 allocate 方法创建了一个指向未初始化内存的 UnsafeMutableRawPointer 对象。byteCount 参数指定了要分配的字节数,这里是 Int 的 8 字节,alignment 参数指定了 Int 的对齐方式。

pointer.storeBytes 这一行代码将值 32 存储到 pointer 指向的内存中。storeBytes 方法用于将值存储到指定内存地址中,as 参数指定了要存储的值的类型,这里传 Int。

pointer.load 这一行代码从 pointer 指向的内存中加载一个 Int 类型的值,并将其赋值给 value 变量。load 方法用于从指定内存地址中加载值,as 参数指定了要加载的值的类型,因此最终打印结果是 32。

UnsafeRawBufferPointer
UnsafeRawBufferPointer 是一个用于访问连续原始内存块中数据的不可变指针。同样实现了 Collection 协议,提供了对内存块的访问和遍历。
var array: [Int] = [1, 2, 3, 4, 5]
let bufferPointer = UnsafeRawBufferPointer(start: &array, count: array.count * MemoryLayout<Int>.size)
bufferPointer.forEach { value in
    print(value)
}

UnsafeMutableRawBufferPointer
UnsafeMutableRawBufferPointer 是一个用于访问连续原始内存块中数据的可变指针。它可以修改内存块。
let pointer = UnsafeMutableRawBufferPointer.allocate(byteCount: 3, alignment: MemoryLayout<Int>.alignment)
pointer.copyBytes(from: [1, 2, 3])
pointer.forEach {
    print($0) // 打印 1, 2, 3
}

用户评论