Подтвердить что ты не робот

Быстро переходит по значению или переходит по ссылке

Я действительно новичок в Swift, и я просто прочитал, что классы передаются по ссылке, массивы/строки и т.д. копируются.

Является ли пропуск по ссылке таким же образом, как в Objective-C или Java, в котором вы фактически передаете ссылку "a" или это правильный проход по ссылке?

4b9b3361

Ответ 1

Типы вещей в Swift

Правило:

  • Экземпляры экземпляров являются ссылочными типами (т.е. ссылка на экземпляр класса является фактически указателем)

  • Функции являются ссылочными типами

  • Все остальное - тип значения; "все остальное" просто означает экземпляры структур и экземпляров перечислений, потому что все это есть в Swift. Например, массивы и строки являются экземплярами структуры. Вы можете передать ссылку на одну из этих вещей (как аргумент функции), используя inout и принимая адрес, как указал newacct. Но тип сам по себе является типом значения.

Какие ссылочные типы означают для вас

Объект ссылочного типа является специальным на практике, потому что:

  • Простое назначение или передача функции может давать несколько ссылок на один и тот же объект

  • Сам объект изменен, даже если ссылка на него является константой (let, явной или подразумеваемой).

  • Мутация объекта затрагивает этот объект, как видно из всех ссылок на него.

Это могут быть опасения, поэтому следите. С другой стороны, передача ссылочного типа явно эффективна, потому что только указатель копируется и передается, что тривиально.

Какие типы значений означают для вас

Очевидно, что передача типа значения "более безопасна", а let означает, что он говорит: вы не можете мутировать экземпляр структуры или экземпляр enum с помощью ссылки let. С другой стороны, эта безопасность достигается путем создания отдельной копии значения, не так ли? Разве это не означает, что значение типа ценности потенциально дорого?

Хорошо, да и нет. Это не так плохо, как вы думаете. Как сказал Нейт Кук, передача типа значения необязательно подразумевает копирование, потому что let (явный или подразумеваемый) гарантирует неизменность, поэтому нет необходимости копировать что-либо. И даже переход в ссылку var не означает, что вещи будут скопированы, только если они будут в случае необходимости (потому что там есть мутация). Документы специально советуют вам не заставлять своих трусиков закручиваться.

Ответ 2

Он всегда передается по значению, когда параметр не inout.

Это всегда pass-by-reference, если параметр inout. Однако это несколько осложняется тем фактом, что вам нужно явно использовать оператор & для аргумента при передаче в параметр inout, поэтому он может не соответствовать традиционному определению pass-by-reference, где вы передаете переменная напрямую.

Ответ 3

Все в Swift передается по умолчанию "copy", поэтому, когда вы передаете тип значения, вы получаете копию значения, а когда вы передаете ссылочный тип, вы получаете копию ссылки, со всем, что влечет за собой. (То есть копия ссылки по-прежнему указывает на тот же экземпляр, что и исходная ссылка.)

Я использую кавычки вокруг "копии" выше, потому что Swift делает большую оптимизацию; где это возможно, он не копирует до тех пор, пока не появится мутация или возможность мутации. Поскольку параметры по умолчанию неизменяемы, это означает, что большую часть времени фактически нет копии.

Ответ 4

Вот небольшой пример кода для передачи по ссылке. Избегайте делать это, если у вас нет веских причин.

func ComputeSomeValues(_ value1: inout String, _ value2: inout Int){
    value1 = "my great computation 1";
    value2 = 123456;
}

Назовите его так:

var val1: String = "";
var val2: Int = -1;
ComputeSomeValues(&val1, &val2);

Ответ 5

В блоге Apple Swift Developer есть сообщение Значение и ссылочные типы, что дает четкое и подробное обсуждение этой темы.

Цитата:

Типы в Swift попадают в одну из двух категорий: во-первых, "типы значений", где каждый экземпляр хранит уникальную копию своих данных, обычно определяемую как структура, перечисление или кортеж. Второй, "ссылочные типы", где экземпляры используют одну копию данных, а тип обычно определяемый как класс.

Сообщение в блоге Swift продолжает объяснять различия с примерами и предлагает, когда вы будете использовать один над другим.

Ответ 6

Когда вы используете inout с инфиксным оператором, таким как + =, символ & address можно игнорировать. Я предполагаю, что компилятор предполагает передачу по ссылке?

extension Dictionary {
    static func += (left: inout Dictionary, right: Dictionary) {
        for (key, value) in right {
            left[key] = value
        }
    }
}

origDictionary + = newDictionaryToAdd

И, к счастью, в этом словаре "add" записывается только одна ссылка на оригинал, что очень хорошо для блокировки!

Ответ 7

Классы передаются по ссылкам, а другие передаются по значению по умолчанию. Вы можете передать ссылку с помощью ключевого слова inout.

Ответ 8

Классы и структуры

Одним из наиболее важных различий между структурами и классами является то, что структуры всегда копируются, когда они передаются в вашем коде, а классы передаются по ссылке.

Затворы

Если вы назначаете замыкание свойству экземпляра класса, и замыкание захватывает этот экземпляр, ссылаясь на экземпляр или его члены, вы создадите сильный ссылочный цикл между замыканием и экземпляром. Swift использует списки захвата, чтобы разорвать эти сильные циклы ссылок

ARC (автоматический подсчет ссылок)

Подсчет ссылок применяется только к экземплярам классов. Структуры и перечисления являются типами значений, а не ссылочными типами, и не хранятся и не передаются по ссылке.