天天看点

Swift3.0 指针 Swift3.0 指针

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

  1. UnsafePointer

    中的

    pointee

    属性只能

    get

    不能

    set

  2. 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

指针。

继续阅读