莫空面试记 1#
午後に b 站で面接を受け、メモリ管理に関する質問をされました。たくさん質問されましたが、この質問が特に印象に残っています。他の質問は分からなかったり、忘れたりしても仕方がないですが、この質問に対して「一塊の糞」と答えてしまったのは本当に心が痛みました。(涙が溢れます)
帰り道にスマホの電池が切れて、これを思い出しました。考えてみると、あれ、これが何か分かる気がする、さらに考えると、やっぱり分かる、そして当時自分が言ったことを考えると、静かにしたいです。
問題を見て、理解すればいい、フォーマットが間違っているとは言わない、大体こんな感じです。
@AutoreleasePool {
A = [[A alloc] init];
B = [[B alloc] init];
A.b = B;
B.a = A;
}
それから、これが循環参照を引き起こしますか?どのステップが原因ですか?説明してもらえますか?
それから私は「一塊の糞」と説明しました。面接官は見かねて、「どうすれば循環参照がなくなるの?」と言いました。
そしてまた「一塊の糞」と言いました。
今考えると、どうしてあんなことを言ったのか?驚いてしまったようです。面接官は、私が OC を学んだことがない C しか知らない人だと仮定して、説明してほしいと言ったのに、私は深い問題だと思い込んで、興奮してしまいました。。。。
ああ、涙が溢れます。もう言わないで、帰り道に思いついた答えを見てみましょう。
まず、循環参照が発生するのは確かです。それから、どのステップかというと、最後のステップです。最後のステップがなければ、循環参照は発生しません。
- A = [[A alloc] init]
このステップで A オブジェクトが作成され、A の参照カウントは 1 になります。 - B = [[B alloc] init]
このステップで B オブジェクトが作成され、B の参照カウントは 1 になります。 - A.b = B
このステップで A オブジェクトが B オブジェクトを保持し、B の参照カウントが 1 増えます。A が B を保持しているため、B を解放するには A が保持している B を先に解放する必要があります。 - B.a = A
このステップで B オブジェクトが A オブジェクトを保持し、A の参照カウントが 1 増えます。同様に、B が A を保持しているため、A を解放するには B が保持している A を先に解放する必要があります。
これで循環参照が発生します。
最後に、どうすれば彼らが正常に解放されるか?もっと簡単です。最後のステップが循環参照を引き起こしているので、最後のステップを変更します。B が A を保持しているため循環参照が発生するので、B が A を保持しないようにします。__weak。。。弱参照を使えば、参照カウントは増えません。
@AutoreleasePool {
A = [[A alloc] init];
B = [[B alloc] init];
A.b = B;
__weak weakB = B;
weakB.a = A;
}