最近试着用Swift基于AudioQueue写一个音乐播放器,但是AudioQueue的API都是C函数,避免不了操作指针。经常卡在指针上,于是决定先静下心来学习一下Swift中的指针。baidu了很多,但是没有系统讲解Swift指针的文章,一边学一边记录,写下这些作为积累。这次学习分为四个部分:UnsafePointer
, UnsafeMutablePointer
, UnsafeRawPointer
, UnsafeMutableRawPointer
。有不对的地方欢迎指出!
在Swift中,指针由结构体 struct UnsafePointer<Pointee>
或 struct UnsafeMutablePointer<Pointee>
表示,但是不能通过”&”获取一个UnsafePointer
或 UnsafeMutablePointer
的实例,只能作为inout
参数使用。UnsafePointer
相对于UnsafeMutablePointer
,其所指向的地址的值是不可变的
一、UnsafeMutablePointer
被UnsafeMutablePointe
引用的内存有三种状态:
1. Not Allocated
2. Allocated but not initialized
3. Allocated and initialized
只有在状态3时,可以安全的使用pointee
属性来set
和get
。
1.初始化
allocate()
initialize()
deinitialize
deallocate()
这四个方法来管理这个指针,并确保指针的pointee
不会出错
(1) allocate
let a_unsafe_mutable_pointer = UnsafeMutablePointer<Int>.allocate(capacity: 0)
Tips:
1. 需要指明要声明的指针类型
2. allocate
是静态方法
(2) initialize
a_unsafe_mutable_pointer.initialize(to: 5)
//或
a_unsafe_mutable_pointer.pointee = 5
这两种方法的结果是相同的
(3) deinitialize
a_unsafe_mutable_pointer.deinitialize(count: 1)
该方法貌似没有真正deintialize,只是返回了一个指向相同地址的UnsafeMutableRawPointer
,并且a_unsafe_mutable_pointer.pointee
仍然是可以正常使用
(4) deallocate
a_unsafe_mutable_pointer.deallocate(capacity: 1)
此时a_unsafe_mutable_pointer不可用了。
2.互相转化
(1) UnsafeMutablePointer -> Swift
let a : Int = a_unsafe_mutable_pointer.pointee
(2) Swift -> UnsafeMutablePointer
let a : UnsafeMutablePointer = &a
以上代码是错误的,只能作为函数参数使用,如下所示
func printPointer(ptr:UnsafeMutablePointer<Int>) {
print("UnsafeMutablePointer:\(ptr)")
print("pointee:\(ptr.pointee)")
}
printPointer(ptr:&a)
将该内存暂时绑定为一种类型,例子中将Int型绑定为Int8
a_unsafe_mutable_pointer.initialize(to: 0x0102030A)
a_unsafe_mutable_pointer.withMemoryRebound(to: Int8.self, capacity: 1, {
ptr in
print(String(ptr.pointee,radix:16)) //1
print(String(ptr.advanced(by: 1).pointee,radix:16)) //2
print(String(ptr.advanced(by: 2).pointee,radix:16)) //3
print(String(ptr.advanced(by: 3).pointee,radix:16)) //a
})
二、UnsafePointer
UnsafePointer
中的pointee
属性只能get
不能set
。UnsafePointer
中没有allocate
方法。
1.初始化
let a_unsafe_pointer = UnsafePointer<Int>.init(a_unsafe_mutable_pointer)
可以由UnsafeMutablePointer
、OpaquePointer
或其他UnsafePointer
创建一个UnsafePointer
指针。其他与UnsafeMutablePointer
类似
2.互相转换
(1) UnsafeMutablePointer -> UnsafePointer
let a_unsafe_pointer = UnsafePointer<Int>.init(a_unsafe_mutable_pointer)
(2) UnsafePointer -> UnsafeMutablePointer
let a_unsafe_mutable_pointer = UnsafePointer<Int>.init(mutating:a_unsafe_pointer)
(3) UnsafePointer -> Swift
let a : Int = a_unsafe_pointer.pointee
(4) Swift -> UnsafePointer
与UnsafeMutablePointer
类似,只能作为函数参数引用
3.withUnsafePointer方法
withUnsafePointer
方法可以直接使用指针,但是不能改变pointee
的值
var a = 0
var b = a
a = withUnsafePointer(to: &a, {
ptr in
return ptr.pointee + 2
//此时,新开辟空间,令a指向该地址,其值为2
//b仍指向a原来的地址,值为0
})
var _ = withUnsafePointer(to: &b, {
ptr in
let size = MemoryLayout<Int>.size //8
//advance(by:Int)移动指针到a
let movedPointer = ptr.advanced(by: -size)
print("b:\(ptr.pointee)") //b = 0
print("a:\(movedPointer.pointee)") //a = 2
})
三、UnsafeMutableRawPointer
UnsafeMutableRawPointer
按我的理解就是无类型的原始指针
1.分配内存
var size = MemoryLayout<Int>.size
//其中alignTo是开辟内存中的对齐,不是很了解,貌似会影响效率,太底层了,不太懂
var a_unsafe_mutable_raw_pointer = UnsafeMutableRawPointer.allocate(bytes: size, alignedTo: size)
这时,这个a_unsafe_mutable_raw_pointer
感觉没啥用,还是需要转换为UnsafeMutablePointer
来对内存进行操作。
2.初始化
初始化内存为Int类型,并赋值为1
a_unsafe_mutable_raw_pointer.initializeMemory(as: Int.self, to: 1)
3.绑定UnsafeMutablePointer
绑定了UnsafeMutablePointer
,使用UnsafeMutablePointer
才能对内存进行赋值,有两种方法绑定:
(1) bindMemory()
该方法绑定内存为指定类型并返回一个UnsafeMutablePointer<指定类型>
的指针
var a_unsafe_mutable_pointer = a_unsafe_mutable_raw_pointer.bindMemory(to: Int.self, capacity: 1)
(2) assumingMemoryBound()
该方法意思是直接转换这个原始指针为一个UnsafeMutablePointer<指定类型>
的指针
var a_unsafe_mutable_pointer = a_unsafe_mutable_raw_pointer.assumingMemoryBound(to: Int.self)
-
这样,就可以使用这个a_unsafe_mutable_pointer
进行其他操作了。
4.deallocate
最后,需要释放内存,首先要deinitialize,再deallocate
a_unsafe_mutable_pointer.deinitialize()
a_unsafe_mutable_raw_pointer.deallocate(bytes: size, alignedTo: size)
5.转换
(1) Swift -> UnsafeMutableRawPointer
var a = 10
var ptr = UnsafeMutableRawPointer(&a)
(2) UnsafeMutableRawPointer -> Swift
其过程应当为UnsafeMutableRawPointer
转换为UnsafeMutablePointer
,再由UnsafeMutablePointer
转换为Swift
指针
四、UnsafeRawPointer
UnsafeRawPointer
只能由其他指针用init
方法得到,与UnsafePointer
类似,没有allocate
静态方法。但是,与UnsafeMutableRawPointer
类似的有两种绑定方法,绑定成UnsafePointer
指针。
https://blog.csdn.net/qq_22879593/article/details/68945564