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: )
Tips:
1. 需要指明要声明的指针类型
2.
allocate
是静态方法
(2) initialize
a_unsafe_mutable_pointer.initialize(to: )
//或
a_unsafe_mutable_pointer.pointee =
这两种方法的结果是相同的
(3) deinitialize
该方法貌似没有真正deintialize,只是返回了一个指向相同地址的
UnsafeMutableRawPointer
,并且
a_unsafe_mutable_pointer.pointee
仍然是可以正常使用
(4) deallocate
此时a_unsafe_mutable_pointer不可用了。
2.互相转化
(1) UnsafeMutablePointer -> Swift
let a : Int = a_unsafe_mutable_pointer.pointee
(2) Swift -> UnsafeMutablePointer
以上代码是错误的,只能作为函数参数使用,如下所示
func printPointer(ptr:UnsafeMutablePointer<Int>) {
print("UnsafeMutablePointer:\(ptr)")
print("pointee:\(ptr.pointee)")
}
printPointer(ptr:&a)
3.暂时绑定
将该内存暂时绑定为一种类型,例子中将Int型绑定为Int8
a_unsafe_mutable_pointer.initialize(to: )
a_unsafe_mutable_pointer.withMemoryRebound(to: Int8.self, capacity: , {
ptr in
print(String(ptr.pointee,radix:)) //1
print(String(ptr.advanced(by: ).pointee,radix:)) //2
print(String(ptr.advanced(by: ).pointee,radix:)) //3
print(String(ptr.advanced(by: ).pointee,radix:)) //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 =
var b = a
a = withUnsafePointer(to: &a, {
ptr in
return ptr.pointee +
//此时,新开辟空间,令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: )
3.绑定UnsafeMutablePointer
绑定了
UnsafeMutablePointer
,使用
UnsafeMutablePointer
才能对内存进行赋值,有两种方法绑定:
(1)
bindMemory()
该方法绑定内存为指定类型并返回一个
UnsafeMutablePointer<指定类型>
的指针
var a_unsafe_mutable_pointer = a_unsafe_mutable_raw_pointer.bindMemory(to: Int.self, capacity: )
(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 =
var ptr = UnsafeMutableRawPointer(&a)
(2) UnsafeMutableRawPointer -> Swift
其过程应当为
UnsafeMutableRawPointer
转换为
UnsafeMutablePointer
,再由
UnsafeMutablePointer
转换为
Swift
指针
四、UnsafeRawPointer
UnsafeRawPointer
只能由其他指针用
init
方法得到,与
UnsafePointer
类似,没有
allocate
静态方法。但是,与
UnsafeMutableRawPointer
类似的有两种绑定方法,绑定成
UnsafePointer
指针。