Я новичок в Swift и только что прочитал, что классы передаются по ссылке, а массивы / строки и т. Д. Копируются.
Проход по ссылке такой же, как в Objective-C или Java, где вы фактически передаете ссылку, или это правильный проход по ссылке?
Я новичок в Swift и только что прочитал, что классы передаются по ссылке, а массивы / строки и т. Д. Копируются.
Проход по ссылке такой же, как в Objective-C или Java, где вы фактически передаете ссылку, или это правильный проход по ссылке?
Ответы:
Правило такое:
Экземпляры класса являются ссылочными типами (т.е. ваша ссылка на экземпляр класса фактически является указателем )
Функции являются ссылочными типами
Все остальное тип значения ; «все остальное» просто означает экземпляры структур и экземпляры перечислений, потому что это все, что есть в Swift. Например, массивы и строки являются экземплярами структур. Вы можете передать ссылку на одну из этих вещей (в качестве аргумента функции), используя inout
и взяв адрес, как указал newacct. Но тип сам по себе является типом значения.
На практике объект ссылочного типа является особенным, потому что:
Простое присвоение или передача функции может дать несколько ссылок на один и тот же объект.
Сам объект является изменяемым, даже если ссылка на него является константой (let
явной или подразумеваемой).
Мутация объекта влияет на этот объект с точки зрения всех ссылок на него.
Это может быть опасно, так что берегитесь. С другой стороны, передача ссылочного типа явно эффективна, потому что копируется и передается только указатель, что тривиально.
Ясно, что передача типа значения «безопаснее» и let
означает то, о чем говорится: вы не можете изменить экземпляр структуры или экземпляр перечисления черезlet
ссылки. С другой стороны, безопасность достигается созданием отдельной копии значения, не так ли? Разве это не делает передачу типа значения потенциально дорогостоящей?
Ну да и нет. Это не так плохо, как вы думаете. Как сказал Нейт Кук, передача типа значения не обязательно подразумевает копирование, потому что let
(явное или подразумеваемое) гарантирует неизменность, поэтому нет необходимости что-либо копировать. И даже переход в var
ссылку не означает, что вещи будут скопированы, только то, что они могут быть при необходимости (потому что есть мутация). В документации особо не советуют выкручивать трусики.
inout
от типа. Является ли что-то передаваемым по ссылке, ортогонально типам.
Это всегда передается по значению, если параметр неinout
.
Если параметр имеет значение, он всегда передается по ссылкеinout
. Однако это несколько усложняется тем фактом, что вам нужно явно использовать &
оператор для аргумента при передаче в inout
параметр, поэтому он может не соответствовать традиционному определению передачи по ссылке, где вы передаете переменную напрямую.
inout
)
inout
на самом деле не передается по ссылке, а только с копированием. Он гарантирует только то, что после вызова функции измененное значение будет присвоено исходному аргументу. In-Out Параметры
Все в Swift по умолчанию передается "копией", поэтому, когда вы передаете тип значения, вы получаете копию значения, а когда вы передаете ссылочный тип, вы получаете копию ссылки со всем, что подразумевается. (То есть копия ссылки по-прежнему указывает на тот же экземпляр, что и исходная ссылка.)
Я использую пугающие кавычки вокруг «копии» выше, потому что Swift много оптимизирует; везде, где это возможно, он не копируется, пока не произойдет мутация или возможность мутации. Поскольку параметры по умолчанию неизменяемы, это означает, что в большинстве случаев копирования фактически не происходит.
Вот небольшой пример кода для передачи по ссылке. Избегайте этого, если у вас нет для этого веской причины.
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);
inout
это оператор копирования в, копирование из. Сначала он скопирует объект, а затем перезапишет исходный объект после возврата из функции. Хотя это может показаться одинаковым, между ними есть небольшие различия.
В блоге Apple Swift Developer есть пост под названием Value and Reference Types. котором содержится четкое и подробное обсуждение этой самой темы.
Цитировать:
Типы в Swift делятся на две категории: во-первых, «типы значений», где каждый экземпляр хранит уникальную копию своих данных, обычно определяемую как структура, перечисление или кортеж. Второй, «ссылочные типы», когда экземпляры совместно используют одну копию данных, а тип обычно определяется как класс.
Сообщение в блоге Swift продолжает объяснять различия с примерами и предлагает, когда вы могли бы использовать одно вместо другого.
По умолчанию классы передаются по ссылкам, а другие по значению. Вы можете передать по ссылке, используя inout
ключевое слово.
inout
это оператор копирования в, копирование из. Сначала он скопирует объект, а затем перезапишет исходный объект после возврата из функции. Хотя это может показаться одинаковым, между ними есть небольшие различия.
Когда вы используете inout с инфиксным оператором, например + =, то символ адреса & можно игнорировать. Полагаю, компилятор предполагает передачу по ссылке?
extension Dictionary {
static func += (left: inout Dictionary, right: Dictionary) {
for (key, value) in right {
left[key] = value
}
}
}
origDictionary + = newDictionaryToAdd
И хорошо, что этот словарь 'add' записывает только одну запись в исходную ссылку, так что отлично подходит для блокировки!
Классы и структуры
Одно из наиболее важных различий между структурами и классами заключается в том, что структуры всегда копируются, когда они передаются в вашем коде, но классы передаются по ссылке.
Закрытие
Если вы назначаете замыкание свойству экземпляра класса, и замыкание захватывает этот экземпляр, ссылаясь на экземпляр или его члены, вы создадите цикл сильных ссылок между замыканием и экземпляром. Swift использует списки захвата, чтобы разорвать эти сильные ссылочные циклы
ARC (автоматический подсчет ссылок)
Подсчет ссылок применяется только к экземплярам классов. Структуры и перечисления являются типами значений, а не ссылочными типами, и не хранятся и не передаются по ссылке.