Не существует такой вещи, как «ДУГА объекта».То, о чем вы думаете, это удержание счета.Трудно представить число более бессмысленным, чем счет удержания.Это либо ноль (в этом случае объект пропал, так что вы никогда этого не увидите), либо «не ноль».
Счет удержания - это количество заявок на владение, которые были предъявленыобъект.Любая часть системы может в любое время заявить о праве собственности.Любая часть системы может отозвать свое право собственности в любое время.Существует целая вещь, называемая пулом авто-выпусков, в котором хранятся заявки на владение, и они будут автоматически аннулироваться "в какой-то момент в будущем".Для объекта совершенно нормально иметь несколько авто-выпусков, которые сохраняются на нем в любой момент времени.Это увеличит количество сохраняемых данных, но количество сохраняемых данных уменьшится позже.
Если количество сохраняемых данных было бессмысленным в MRC (и они были), они полностью помешали в ARC, где компилятор может оптимизировать ихв любое время он может доказать, что это не имеет значения, и часто вводит дополнительные удержания, когда не может доказать, что они не нужны (особенно связанные с вызовами функций).Таким образом, фактическая стоимость еще более бессмысленна.Например, в ARC для test
вполне уместно добавить дополнительное удержание перед вызовом CFGetRetainCount
, чтобы убедиться, что test
не высвобождается слишком быстро.
Если выЕсли у вас проблемы с управлением памятью, вы хотите использовать такие инструменты, как отладчик графа памяти (и просто искать надежные ссылки и особенно сильные циклы).Проверка количества записей будет ложью только для вас.
В вашем конкретном случае мы можем исследовать это немного с помощью swiftc -emit-sil
, начиная с того момента, когда мы выполняем интерполяцию строк (то есть ""
в последнемстрока):
// function_ref String.init(_builtinStringLiteral:utf8CodeUnitCount:isASCII:)
%34 = function_ref @$SSS21_builtinStringLiteral17utf8CodeUnitCount7isASCIISSBp_BwBi1_tcfC : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %35
%35 = apply %34(%30, %31, %32, %33) : $@convention(method) (Builtin.RawPointer, Builtin.Word, Builtin.Int1, @thin String.Type) -> @owned String // user: %37
%36 = alloc_stack $String // users: %39, %37, %41
store %35 to %36 : $*String // id: %37
// function_ref specialized String.init<A>(stringInterpolationSegment:)
%38 = function_ref @$SSS26stringInterpolationSegmentSSx_tcs23CustomStringConvertibleRzs20TextOutputStreamableRzlufCSS_Tg5 : $@convention(method) (@owned String, @thin String.Type) -> @owned String // user: %40
%39 = load %36 : $*String // user: %40
%40 = apply %38(%39, %29) : $@convention(method) (@owned String, @thin String.Type) -> @owned String // user: %42
dealloc_stack %36 : $*String // id: %41
store %40 to %28 : $*String // id: %42
%43 = integer_literal $Builtin.Word, 1 // user: %44
%44 = index_addr %28 : $*String, %43 : $Builtin.Word // user: %58
%45 = metatype $@thin String.Type // user: %56
%46 = load %3 : $*LevelBuilder // users: %48, %47
=========
strong_retain %46 : $LevelBuilder // id: %47
%48 = init_existential_ref %46 : $LevelBuilder : $LevelBuilder, $AnyObject // user: %49
%49 = enum $Optional<AnyObject>, #Optional.some!enumelt.1, %48 : $AnyObject // users: %52, %51
// function_ref CFGetRetainCount
%50 = function_ref @CFGetRetainCount : $@convention(c) (Optional<AnyObject>) -> Int // user: %51
%51 = apply %50(%49) : $@convention(c) (Optional<AnyObject>) -> Int // user: %54
release_value %49 : $Optional<AnyObject> // id: %52
=========
Важную часть я пометил ===
строками.Сильное удержание накладывается на test
.Затем он помещается в оболочку AnyObject?
для передачи в функцию C (GetRetainCount
).Функция называется.И тогда значение Optional (то есть test
) освобождается.Поэтому вы должны ожидать одно дополнительное сохранение при вызове GetRetainCount
.
Но если вы перекомпилируете это с -O
, вы заметите, что инструкции strong_retain
нет.ARC видит, что дополнительное удержание на самом деле не нужно, и удаляет его.Таким образом, это говорит о том, что с оптимизацией количество сохранений будет равно 1. Интересно, правда ли это:
$ swiftc main.swift
$ ./main
ARC: 2
$ swiftc -O main.swift
$ ./main
ARC: 1
Конечно.