UnsafeMutablePointer
声明
@frozen struct UnsafeMutablePointer<Pointee>
概述
您使用UnsafeMutablePointer
类型的实例来访问内存中特定类型的数据。指针可以访问的数据类型是指针的Pointee
类型。 UnsafeMutablePointer
不提供自动内存管理或对齐保证。您负责通过不安全的指针处理您使用的任何内存的生命周期,以避免泄漏或未定义的行为。
您手动管理的内存可以是特定类型的untyped
或bound
。您使用UnsafeMutablePointer
类型来访问和管理已绑定到特定类型的内存。
了解指针的内存状态
UnsafeMutablePointer
实例引用的内存可以处于多种状态之一。许多指针操作只能应用于内存处于特定状态的指针——您必须跟踪正在使用的内存的状态,并了解不同操作执行的对该状态的更改。内存可以是无类型的和未初始化的,绑定到一个类型但未初始化,或者绑定到一个类型并初始化为一个值。最后,先前分配的内存可能已被释放,留下现有指针引用未分配的内存。
未初始化的内存
刚刚通过类型化指针分配或已取消初始化的内存处于uninitialized
状态。必须先初始化未初始化的内存,然后才能访问它以进行读取。
您可以使用 initialize(repeating:count:)
、 initialize(from:count:)
和 moveInitialize(from:count:)
之类的方法来用一个值或一系列值初始化指针所引用的内存。
初始化内存
Initialized
内存具有可以使用指针的 pointee
属性或通过下标表示法读取的值。在下面的示例中,ptr
是一个指向内存的指针,初始化为 23
:
let ptr: UnsafeMutablePointer<Int> = ...
// ptr.pointee == 23
// ptr[0] == 23
以不同类型访问指针的内存
通过UnsafeMutablePointer
实例访问内存时,Pointee
类型必须与内存的绑定类型一致。如果您确实需要将绑定到一种类型的内存作为不同类型访问,Swift 的指针类型提供了type-safe 方法来临时或永久更改内存的绑定类型,或者直接从原始内存加载类型化实例。
分配有八字节内存的 UnsafeMutablePointer<UInt8>
实例 uint8Pointer
将用于以下示例。
var bytes: [UInt8] = [39, 77, 111, 111, 102, 33, 39, 0]
let uint8Pointer = UnsafeMutablePointer<UInt8>.allocate(capacity: 8)
uint8Pointer.initialize(from: &bytes, count: 8)
当您只需要临时以不同类型访问指针的内存时,请使用withMemoryRebound(to:capacity:)
方法。例如,您可以使用此方法调用 API,该 API 需要指向与您的指针的 Pointee
布局兼容的不同类型的指针。下面的代码临时将uint8Pointer
引用的内存从UInt8
重新绑定到Int8
,以调用导入的Cstrlen
函数。
// Imported from C
func strlen(_ __s: UnsafePointer<Int8>!) -> UInt
let length = uint8Pointer.withMemoryRebound(to: Int8.self, capacity: 8) {
return strlen($0)
}
// length == 7
当您需要将内存永久重新绑定到不同类型时,首先获取指向内存的原始指针,然后在原始指针上调用bindMemory(to:capacity:)
方法。以下示例将 uint8Pointer
引用的内存绑定到 UInt64
类型的一个实例:
let uint64Pointer = UnsafeMutableRawPointer(uint8Pointer)
.bindMemory(to: UInt64.self, capacity: 1)
在将 uint8Pointer
引用的内存重新绑定到 UInt64
后,作为 UInt8
实例访问该指针的引用内存是未定义的。
var fullInteger = uint64Pointer.pointee // OK
var firstByte = uint8Pointer.pointee // undefined
或者,只要绑定类型和目标类型是普通类型,您就可以访问相同的内存作为不同类型,而无需通过非类型化内存访问重新绑定。将指针转换为 UnsafeMutableRawPointer
实例,然后使用原始指针的 load(fromByteOffset:as:)
和 storeBytes(of:toByteOffset:as:)
方法读取和写入值。
let rawPointer = UnsafeMutableRawPointer(uint64Pointer)
let fullInteger = rawPointer.load(as: UInt64.self) // OK
let firstByte = rawPointer.load(as: UInt8.self) // OK
执行类型化指针算术
具有类型化指针的指针算术以指针的Pointee
类型的步长计数。当您添加到 UnsafeMutablePointer
实例或从 UnsafeMutablePointer
实例减去时,结果是相同类型的新指针,偏移量为 Pointee
类型的实例数。
// 'intPointer' points to memory initialized with [10, 20, 30, 40]
let intPointer: UnsafeMutablePointer<Int> = ...
// Load the first value in memory
let x = intPointer.pointee
// x == 10
// Load the third value in memory
let offsetPointer = intPointer + 2
let y = offsetPointer.pointee
// y == 30
您还可以使用下标表示法来访问内存中特定偏移量的值。
let z = intPointer[2]
// z == 30
隐式转换和桥接
当使用 UnsafeMutablePointer
参数调用函数或方法时,您可以传递该特定指针类型的实例或使用 Swift 的隐式桥接来传递兼容的指针。
例如,以下代码示例中的 printInt(atAddress:)
函数需要一个 UnsafeMutablePointer<Int>
实例作为其第一个参数:
func printInt(atAddress p: UnsafeMutablePointer<Int>) {
print(p.pointee)
}
与 Swift 中的典型情况一样,您可以使用 UnsafeMutablePointer
实例调用 printInt(atAddress:)
函数。此示例将 intPointer
(指向 Int
值的可变指针)传递给 print(address:)
。
printInt(atAddress: intPointer)
// Prints "42"
或者,您可以使用 Swift 的 implicit bridging
将指针传递给实例或数组的元素。以下示例使用 inout 语法传递指向 value
变量的指针:
var value: Int = 23
printInt(atAddress: &value)
// Prints "23"
使用 inout 语法传递数组时,会隐式创建指向数组元素的可变指针。此示例在调用 printInt(atAddress:)
时使用隐式桥接将指针传递给 numbers
的元素。
var numbers = [5, 10, 15, 20]
printInt(atAddress: &numbers)
// Prints "5"
无论你以哪种方式调用 printInt(atAddress:)
,Swift 的类型安全保证你只能传递一个指向函数所需类型的指针——在本例中,是一个指向 Int
的指针。
可用版本
相关用法
- Swift UnsafeMutablePointer allocate(capacity:)用法及代码示例
- Swift UnsafeMutablePointer withMemoryRebound(to:capacity:_:)用法及代码示例
- Swift UnsafeMutablePointer ..<(_:)用法及代码示例
- Swift UnsafeMutablePointer move()用法及代码示例
- Swift UnsafeMutablePointer ...(_:)用法及代码示例
- Swift UnsafeMutablePointer ...(_:_:)用法及代码示例
- Swift UnsafeMutablePointer ..<(_:_:)用法及代码示例
- Swift UnsafeMutableRawPointer ..<(_:_:)用法及代码示例
- Swift UnsafeMutableBufferPointer allocate(capacity:)用法及代码示例
- Swift UnsafeMutableRawPointer ...(_:_:)用法及代码示例
- Swift UnsafeMutableBufferPointer prefix(through:)用法及代码示例
- Swift UnsafeMutableRawBufferPointer shuffle()用法及代码示例
- Swift UnsafeMutableBufferPointer map(_:)用法及代码示例
- Swift UnsafeMutableRawBufferPointer compactMap(_:)用法及代码示例
- Swift UnsafeMutableRawPointer initializeMemory(as:repeating:count:)用法及代码示例
- Swift UnsafeMutableRawBufferPointer contains(where:)用法及代码示例
- Swift UnsafeMutableRawBufferPointer allSatisfy(_:)用法及代码示例
- Swift UnsafeMutableRawBufferPointer map(_:)用法及代码示例
- Swift UnsafeMutableBufferPointer filter(_:)用法及代码示例
- Swift UnsafeMutableRawPointer advanced(by:)用法及代码示例
- Swift UnsafeMutableBufferPointer elementsEqual(_:)用法及代码示例
- Swift UnsafeMutableRawBufferPointer starts(with:)用法及代码示例
- Swift UnsafeMutableRawBufferPointer isEmpty用法及代码示例
- Swift UnsafeMutableRawBufferPointer sorted()用法及代码示例
- Swift UnsafeMutableBufferPointer reduce(into:_:)用法及代码示例
注:本文由纯净天空筛选整理自apple.com大神的英文原创作品 UnsafeMutablePointer。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。