Я новичок в 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 (автоматический подсчет ссылок)
Подсчет ссылок применяется только к экземплярам классов. Структуры и перечисления являются типами значений, а не ссылочными типами, и не хранятся и не передаются по ссылке.