Создает ли Swift копию параметра, переданного в функцию? [Дубликат]

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

71
задан gran_profaci 8 December 2014 в 19:06
поделиться

6 ответов

Типы вещей в Swift

Правило:

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

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

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

  • Простое назначение или передача функции может давать несколько ссылок на один и тот же объект
  • Сам объект изменен, даже если ссылка на него является константой (let, явной или подразумеваемой).
  • Мутация объекта затрагивает этот объект, как видно из всех ссылок на него.

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

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

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

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

120
ответ дан matt 19 August 2018 в 06:54
поделиться
  • 1
    Экземпляры класса передаются по ссылке. Функции передаются по ссылке & quot; Неа. Это значение передается по значению, если параметр не является inout независимо от типа. Независимо от того, что-то передается по ссылке, ортогонально к типам. – newacct 9 December 2014 в 02:36
  • 2
    @newacct Ну, конечно, вы правы в строгом смысле! Строго говоря, нужно сказать, что все имеет значение pass-by-value, но экземпляры enum и экземпляры структуры - это типы значений , а экземпляры и функции класса - это ссылочные типы . См. Например, developer.apple.com/swift/blog/?id=10 . Также см. developer.apple.com/library/ios/documentation/Swift/Conceptual/… Однако, я думаю, что то, что я сказал, согласуется с общим смыслом слов. – matt 9 December 2014 в 02:42
  • 3
    Правильно, а типы значений / ссылочные типы не следует путать с параметром pass-by-value / pass-by-reference, поскольку типы значений могут передаваться по значению или по ссылке, а ссылочные типы также могут передаваться по значению или по ссылке. – newacct 9 December 2014 в 02:45
  • 4
    @newacct очень полезное обсуждение; Я переписываю свое резюме, чтобы оно не вводило в заблуждение. – matt 9 December 2014 в 15:54
  • 5
    «Документы специально советуют вам не заставлять своих трусиков закручиваться». - Ха-ха! – user 15 January 2017 в 18:06

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

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);
3
ответ дан Chris Amelinckx 19 August 2018 в 06:54
поделиться

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

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

30
ответ дан Nate Cook 19 August 2018 в 06:54
поделиться

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

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

33
ответ дан newacct 19 August 2018 в 06:54
поделиться
  • 1
    Этот ответ, в сочетании с Nate Cook's, был более ясным для меня (из C ++) вокруг того факта, что даже «ссылочный тип» будет not изменен вне функции scope , если вы явно не укажете его (используя inout) – Gobe 22 March 2016 в 13:34
  • 2
    inout на самом деле не проходит по ссылке, но copy-in copy-out . Это гарантирует, что после изменения функционального вызова исходный аргумент будет назначен. Параметры входа – Dalija Prasnikar 13 April 2017 в 19:41

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

0
ответ дан Undo 19 August 2018 в 06:54
поделиться

В блоге разработчика Apple Swift есть сообщение с именем Value и Reference Types , в котором дается четкое и подробное обсуждение этой темы.

Цитируя:

< blockquote>

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

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

6
ответ дан whyceewhite 19 August 2018 в 06:54
поделиться
  • 1
    Это не отвечает на вопрос. Возникает вопрос о посылке по сравнению с передачей по ссылке, которая полностью ортогональна типам значений по сравнению с ссылочными типами. – Jörg W Mittag 4 October 2016 в 21:52
Другие вопросы по тегам:

Похожие вопросы: