Does Swift close fixed variables?

I found that Swift closures do not save captured variables, unlike my expectation.

class AAA { } var a1 = AAA() as AAA? // expects RC == 1 var a2 = { ()->AAA? in return a1 } // expects RC == 2, retained by `Optional<AAA>` a1 = nil // expects RC == 1 a2() // prints nil, ???? 

I am very confused by this, because it was believed that the captured variables would be saved by default. But, if I commit it explicitly with the capture list, it is saved.

 class AAA { } var a1 = AAA() as AAA? var a2 = { [a1]()->AAA? in return a1 } a1 = nil a2() // prints {AAA}, alive as expected. 

I re-read the Swift manual, but I could not find the corresponding description. The capture list is used to set unowned explicitly, and I'm still confused. What is the correct behavior and why is this happening?

+5
source share
3 answers

Yes, documented in Capture Values :

Swift determines what should be written by reference and what needs to be copied by value. You do not need to specify a sum or runningTotal to say that they can be used inside the incrementor nested function. Swift also handles all the memory management involved in the runTotal utilization when it is no longer needed by the increment function.

Rule: if you refer to a captured variable without modifying it, it is fixed by value. If you change it instead, it will be removed by reference. Of course, unless you explicitly override this by defining a capture list.

Addendum The above statements appear to be incorrect. Captures are made by reference, regardless of whether they were changed or not in the close. Read the @newacct comment.

+5
source

I posted the same question on the Apple Developer Forum, and there was a discussion . Although people don't talk too much about links, I got some ideas. Here is my conclusion:

  • A value is always copied when it is associated with a new (explicit) name. Regardless of var or let .
  • Copied to reference types means RC + 1. Because it copies a strong pointer, such as C ++ shared_ptr<T> .
  • Closing (closing a capture) does not change anything because there is no new name. This is the same as using them on the same stack. This is what reference means. It has nothing to do with RC and does not change RC, because it is something like C ++ references.
  • A capture list is an explicit ( let ) name. Therefore, it invokes copying and makes RC + 1.
  • When a close function returns from a function, it can be bound to a name. If so, RC + 1 due to a new name binding.
  • RC-1, when a value (such a strong pointer) is not associated with its name.
  • An implicit reference to self is the only exception that makes implicit name binding.

And there are many optimizations without violating these rules, anyway, these are just implementation details.

+1
source

Your example does not make sense @newacct. The variable x actually changes outside the block. Swift is smart enough to find out if you are changing a variable inside or outside of a closure.

As the document says:

As an optimization, Swift can instead capture and save a copy of the value if that value is not mutated by the closure or outside.

Regarding the post by @Eonil question, in the first snippet, you have a strong reference to Optional<AAA> in the close. However, when you set a1 to nil, what you are actually doing is removing the value of type AAA, which is wrapped inside optional.

When you call closure a2 , you return the same optional, with no value inside, which exactly means nil . So having a strong link means your close has the same meaning as a1 . This does not mean that this optional parameter cannot be set to nil.

In the second code snippet, you wrote a1 to the capture list. This means that you copy a1 and the value of a1 inside the closure has nothing to do with the value of a1 outside the closure. Therefore, even if you set a1 to zero, it does not affect what you get from closing.

My English is not very good, and I hope that I expressed my opinion clearly. Or you can read this article , I think this will help you a lot.

+1
source

Source: https://habr.com/ru/post/1205546/


All Articles