w C/Objective-C Blocks terminologii memo
jest __block
zmienna (w Swift, nie trzeba jawnie napisz __block
, aby przechwycić zmienne przez odniesienie). Zmienna może być przypisana do bloku (zamknięcia) i wszystkich zakresów, które widzą, że zmienna zobaczy zmiany z dowolnej innej zmiennej (współużytkują odniesienie do zmiennej). Zmienna będzie ważna, dopóki jakiś blok (zamknięcie), który jej używa (jest tylko jeden blok, który używa go w tym przypadku) jest wciąż żywy. Po zwolnieniu ostatniego bloku, zmienna wykracza poza zakres. Jak to działa, jest szczegółem implementacji.
Jeśli ta zmienna ma typ wskaźnika obiektu, to wskazywany obiekt zostanie zachowany przez bloki przechwytujące. Jednak w tym przypadku zmienną jest Dictionary
, typ struktury, który jest typem wartości. Dlatego nie trzeba się martwić o zarządzanie pamięcią. Zmienna jest strukturą, a struktura żyje tak długo, jak zmienna. (Sama struktura może przydzielić pamięć gdzie indziej i zwolnić ją w swoim destruktorze, ale to jest wewnętrznie obsługiwane przez strukturę, a zewnętrzna strona nie powinna o tym wiedzieć ani się tym nie przejmować.)
Zazwyczaj nie trzeba się martwić o to, jak __block
zmienne działają wewnętrznie. Zasadniczo zmienna jest zawijana w uproszczony "obiekt", rzeczywista "zmienna" jest polem tego "obiektu", którym zarządza się pamięcią poprzez liczenie odwołań. Bloki, które je przechwytują, posiadają "silne referencje" do tego pseudoobiektu - kiedy blok zostanie utworzony na stercie (technicznie, gdy są one kopiowane z bloków stosu do sterty), który używa tej zmiennej __block
, zwiększa ona liczbę odnośników ; gdy blok korzystający z niego jest zwolniony, zmniejsza liczbę odwołań. Gdy licznik odwołań wynosi 0, ten pseudo "obiekt" zostaje zwolniony, wywołując najpierw odpowiedni destruktor dla jego typu zmiennej.
Aby odpowiedzieć na pytanie, "zapamiętana funkcja fibonacci" jest blokiem (zamknięciem). I to właśnie ma silne odniesienie do tego, co zawiera zmienną memo
. "Inwokacje" nie mają silnych lub słabych odniesień do niego; gdy funkcja jest wywoływana, używa odwołania, które sama funkcja ma.Żywotność zmiennej memo
jest czasem życia "zapamiętanej funkcji fibonacci" w tym przypadku, ponieważ jest to jedyne zamknięcie przechwytujące tę zmienną.
To nie to samo, co ten kod, ponieważ wiele zamknięć może przechwycić tę zmienną, a zmienna byłaby stanem wspólnym dla wszystkich zamknięć. Dodatkowo stan zmienny jest również dzielony między zamknięciem i kodem poza zamknięciem (to jest kod w funkcji 'memoize' bezpośrednio może również odczytywać i zapisywać' memo'). – newacct
@newacct Kod ma na celu zilustrowanie tego konkretnego przypadku, a nie zamknięcia w ogóle. – hamstergene