Why can’t I initialize a Swift UnsafeMutablePointer<UInt32> with (&myUInt32) or (&[myUInt32])

六月ゝ 毕业季﹏ 提交于 2019-12-11 11:42:16

问题


The docs say: "When a function is declared as taking an UnsafeMutablePointer argument, it can accept any of the following... An in-out expression whose operand is a stored lvalue of type Type, which is passed as the address of the lvalue." I can copy the example and demonstrate this.

func takesAMutablePointer<T>(x: UnsafeMutablePointer<T>) -> UnsafeMutablePointer<T>
    {
        return x
    }

func useAMutablePointer()
    {
        var legInt :UInt32 = 42
        var legIntArray: [UInt32] = [legInt]
        var legIntPtr: UnsafeMutablePointer<UInt32>
        legIntPtr = takesAMutablePointer(&legInt)
        legIntPtr = takesAMutablePointer(&legIntArray)
        legIntPtr = UnsafeMutablePointer(&legInt) //Compile error!
        legIntPtr = UnsafeMutablePointer(&legIntArray) //Compile error!
    }

Xcode shows that UnsafeMutablePointer has the following initializer:

init<U>(_ from: UnsafeMutablePointer<U>) , but when I try to use it like my function, the compiler error is Cannot find an initializer for type 'UnsafeMutablePointer<T>' that accepts an argument list of type '(inout UInt32)' So,

  1. What's the direct way to get an UnsafeMutablePointer<UInt32> to legInt?
  2. Why can’t I use the initializer as expected?

Thanks!


回答1:


I am a little bit speculating here, but the reason seems to be that UnsafeMutablePointer<T> has generic initializer

init<U>(_ from: UnsafeMutablePointer<U>)

where <U> is unrelated to <T>. It seems that the compiler cannot infer the type <U> in

legIntPtr = UnsafeMutablePointer(&legInt) //Compile error!

Just to confirm this conjecture, we can define a custom extension

extension UnsafeMutablePointer {
    init(_ from : UnsafeMutablePointer<T>) {
    // Swift 2: init(_ from : UnsafeMutablePointer<Memory>) {
        self = from
    }
}

which initializes the pointer from another pointer of the same type. Now all your code compiles and works as expected.

What you can do is use withUnsafeMutablePointer():

legIntPtr = withUnsafeMutablePointer(&legInt, { $0 })

But keep in mind that the compiler does not track this pointer to the object as a reference and might destroy the object. That's why these pointers are "unsafe". You should normally use the pointer only inside the withUnsafeMutablePointer() closure.



来源:https://stackoverflow.com/questions/29976346/why-can-t-i-initialize-a-swift-unsafemutablepointeruint32-with-myuint32-or

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!