Почему я не могу инициализировать Swift UnsafeMutablePointer‹UInt32› с помощью (&myUInt32) или (&[myUInt32])

В документах говорится: «Когда функция объявлена ​​как принимающая аргумент UnsafeMutablePointer, она может принимать любое из следующего... Выражение входа-выхода, операндом которого является сохраненное значение lvalue типа Type, которое передается как адрес lvalue. ." Я могу скопировать пример и продемонстрировать это.

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 показывает, что UnsafeMutablePointer имеет следующий инициализатор:

init<U>(_ from: UnsafeMutablePointer<U>) , но когда я пытаюсь использовать его как свою функцию, ошибка компилятора Cannot find an initializer for type 'UnsafeMutablePointer<T>' that accepts an argument list of type '(inout UInt32)' Итак,

  1. Какой прямой способ получить UnsafeMutablePointer<UInt32> для legInt?
  2. Почему я не могу использовать инициализатор, как ожидалось?

Спасибо!


person Charlweed    schedule 30.04.2015    source источник
comment
Прямого пути нет. Есть некоторые обходные пути, но нет прямых путей. Swift поддерживает указатели только для обеспечения взаимодействия с C.   -  person Sulthan    schedule 30.04.2015


Ответы (1)


Здесь я немного рассуждаю, но причина, по-видимому, в том, что UnsafeMutablePointer<T> имеет общий инициализатор

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

где <U> не имеет отношения к <T>. Кажется, что компилятор не может вывести тип <U> в

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

Просто чтобы подтвердить эту гипотезу, мы можем определить пользовательское расширение

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

который инициализирует указатель из другого указателя того же типа. Теперь весь ваш код компилируется и работает как положено.

Что вы можете сделать, так это использовать withUnsafeMutablePointer():

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

Но имейте в виду, что компилятор не отслеживает этот указатель на объект как ссылку и может уничтожить объект. Вот почему эти указатели "небезопасны". Обычно указатель следует использовать только внутри замыкания withUnsafeMutablePointer().

person Martin R    schedule 30.04.2015
comment
Есть ли документация Apple по withUnsafeMutablePointer ? Похоже, это не язык программирования Swift и не использование Swift с Cocoa и Objective C. Google скромничает... - person Charlweed; 04.05.2015
comment
@Charlweed: я ничего не знаю. Но вы можете нажать на функцию с помощью команды, чтобы получить ее определение с поясняющими комментариями. Или используйте автоматически сгенерированную документацию по адресу swiftdoc.org/func/withUnsafeMutablePointer. - person Martin R; 04.05.2015