zoukankan      html  css  js  c++  java
  • Swift 中的指针使用

    SWIFT 中  指针被映射为泛型 

    UnsafePointer<T> 

    UnsafeMutablePointer<T>

    表示一组连续数据指针的 UnsafeBufferPointer<T>

    表示非完整结构的不透明指针 COpaquePointer 等等

     

    UnsafePointer<T> 通过 memory 属性对其进行取值,如果这个指针是可变的 UnsafeMutablePointer<T> 类型,我们还可以通过 memory 对它进行赋值。

    1
    2
    3
    4
    5
    6
    7
    func incrementor(ptr: UnsafeMutablePointer<Int>) {
        ptr.memory += 1
    }
      
    var a = 10
    incrementor(&a)
    // 11

    swift中&同样可以取地址, 但无法直接获取一个指针实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var a = 10
    //let ptr:UnsafeMutablePointer<Int> = &a // 'inout Int' is not convertible to 'UnsafeMutablePointer<Int>'
    //let ptr2 = &a                          // 报错
    func incrementor1(inout num: Int) {
        num += 1
    }
     
    var b = 10
    incrementor1(&b)
    b   // 11
    1
    2
    3
    4
    5
    6
    7
    [1,2,3] + 1  // 不报错,Playground显示一个地址值
    ([1,2,3] + 1)[-100]  // 不报错
    ([1,2,3] + 1)[30]
     
    var array = [1,2,3]
    //array + 1     //报错
     //let ptr:UnsafeMutableBufferPointer<Int> = array  //报错

     当使用inout运算符时,使用var声明的变量和使用let声明的常量被分别转换到UnsafePointer和UnsafeMutablePoinger

     

     在 Swift 中不能直接取到现有对象的地址,我们还是可以创建新的 UnsafeMutablePointer 对象。与 Swift 中其他对象的自动内存管理不同,对于指针的管理,是需要我们手动进行内存的申请和释放的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    // 将向系统申请 1 个 Int 大小的内存,并返回指向这块内存的指针
    var intPtr = UnsafeMutablePointer<Int>.alloc(1)
    // 初始化
    intPtr.initialize(10)
    var intPtr2 = intPtr.successor()
    intPtr2.initialize(50)
    // 读取值
    intPtr.memory   // 10
    intPtr2.memory   // 20
     
    //intPtr.dealloc(1)
    //intPtr.destroy(1)//
    intPtr.destroy()
    intPtr2 = nil
    //intPtr2.memory  // 奔溃
     
     
     
    var array = [1,2,3]
    let arrayPtr = UnsafeMutableBufferPointer<Int>(start: &array, count: array.count)
    // baseAddress 是第一个元素的指针
    var basePtr = arrayPtr.baseAddress as UnsafeMutablePointer<Int>
     
    basePtr.memory // 1
    basePtr.memory = 10
    basePtr.memory // 10
     
    //下一个元素
    var nextPtr = basePtr.successor()
    nextPtr.memory // 2

     直接操作变量地址 withUnsafePointer,withUnsafePointers

    1
    2
    3
    4
    5
    6
    7
    var test = 10
    test = withUnsafeMutablePointer(&test, { (ptr: UnsafeMutablePointer<Int>) -> Int in
        ptr.memory += 1
        return ptr.memory
    })
     
    test // 11

     

    unsafeBitCast

    unsafeBitCast 是非常危险的操作,它会将一个指针指向的内存强制按位转换为目标的类型。因为这种转换是在 Swift 的类型管理之外进行的,因此编译器无法确保得到的类型是否确实正确,你必须明确地知道你在做什么。比如:

    1
    2
    3
    4
    5
    6
    let arr = NSArray(object: "meow")
    let str = unsafeBitCast(CFArrayGetValueAtIndex(arr, 0), CFString.self)
    str // “meow”
     
    let arr2 = ["meow2"]
    let str2 = unsafeBitCast(CFArrayGetValueAtIndex(arr2, 0), CFString.self)

     

    因为 NSArray 是可以存放任意 NSObject 对象的,当我们在使用 CFArrayGetValueAtIndex 从中取值的时候,得到的结果将是一个 UnsafePointer<Void>。由于我们很明白其中存放的是 String 对象,因此可以直接将其强制转换为 CFString。

    关于 unsafeBitCast 一种更常见的使用场景是不同类型的指针之间进行转换。因为指针本身所占用的的大小是一定的,所以指针的类型进行转换是不会出什么致命问题的。这在与一些 C API 协作时会很常见。比如有很多 C API 要求的输入是 void *,对应到 Swift 中为 UnsafePointer<Void>。我们可以通过下面这样的方式将任意指针转换为 UnsafePointer。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var count = 100
    var voidPtr = withUnsafePointer(&count, { (a: UnsafePointer<Int>) -> UnsafePointer<Void> in
        return unsafeBitCast(a, UnsafePointer<Void>.self)
    })
    // voidPtr 是 UnsafePointer<Void>。相当于 C 中的 void *
    voidPtr.memory //Void
     
    // 转换回 UnsafePointer<Int>
    var intPtr = unsafeBitCast(voidPtr, UnsafePointer<Int>.self)
    intPtr.memory //100
  • 相关阅读:
    hdu 2544 Dijstra模板题
    hdu 1002 prime 模板
    POJ_2653_Pick-up sticks_判断线段相交
    POJ_1556_The Doors_判断线段相交+最短路
    POJ_1269_Intersecting Lines_求直线交点
    POJ_3304_Segments_线段判断是否相交
    POJ_2318_TOYS&&POJ_2398_Toy Storage_二分+判断直线和点的位置关系
    ZOJ_2314_Reactor Cooling_有上下界可行流模板
    LuoguP4234_最小差值生成树_LCT
    BZOJ_3996_[TJOI2015]线性代数_最大权闭合子图
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/5946901.html
Copyright © 2011-2022 走看看