Swift3.0 指针
最近试着用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)
3.暂时绑定
将该内存暂时绑定为一种类型,例子中将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指针。
1753

被折叠的 条评论
为什么被折叠?



