質問: makeIncrementer(10, 5) inc() // 15 inc() // 20 inc() // 25 ```
回答: 詳解Swift 荻原剛志著 この書籍の、「Chapter12 クロージャ、12.2 変数のキャプチャ」に、説明があります。ひとことで説明すると、クロージャがローカル変数を参照し続けているので、ローカル変数は解放されず、メモリに保持されたままになる、ということだそうです。誤解を与えてはいけないので、詳しくは、この書籍に直接あたってください。 クロージャ(というより、この場合はネスト関数)を解放すれば、ローカル変数も解放されます。 ``` // 解放されるタイミングを調べるため、deinitを実装したクラスを定義する。 class MyClass { var lValue: Int = 0 init(lValue: Int) { self.lValue = lValue } deinit { print("Released with \(lValue)") // 解放された時点のlValueの値を出力 } } func makeIncrementer(lValue a: MyClass, rValue b: Int) -> () -> Int { var innerValue = a.lValue func incrementer() -> Int { innerValue += b a.lValue = innerValue return innerValue } return incrementer } // nilを代入して解放するためにOptional型で宣言する。 var myClass: MyClass! = MyClass(lValue: 20) // nilを代入して解放するためにOptional型で宣言する。 var innerFunc: (() -> Int)! = makeIncrementer(lValue: myClass, rValue: 10) // 20に10を加算する。 innerFunc() // 30 innerFunc() // 40 myClass = nil // myClassを解放しようとするが、deinitが呼ばれない。 innerFunc() // 50 innerFunc = nil // 出力:Released with 50 // innerFuncを解放した時点で、myClassが解放されたことがわかる。 ```