Objective-Cを勉強中に出た疑問の自分用メモ。
メモリ管理に使っているリファレンスカウンタについて。
お勉強のため、ARCはオフ。
勉強資料は以下のサイト。
今さら聞けないObjective-Cのメモリ管理 弱い参照と強い参照って何? | Developers.IO
#import "Car.h"
@implementation Car
/* setter を使う場合 */
- (void)setEngine:(Engine *)newEngine {
[newEngine retain];
[engine release];
engine = newEngine;
}
/* property を使う場合
@synthesize engine;
*/
- (void)dealloc {
NSLog(@"dealloc Car");
[engine release];
[super dealloc];
}
@end
何がわからなかったかっていうと、setEngine:のあたり。
- (void)setEngine:(Engine *)newEngine {
[newEngine retain]; // newEngineのリファレンスカウンタは2
[engine release]; // engineのリファレンスカウンタは0
engine = newEngine; // engineのリファレンスカウンタは2 ←!?!?!?!?!?
}
なんで急にengineのリファレンスカウンタが2になんのよ!
retainしてないぞ!ってのが今回の疑問。
newEngineインスタンスをengineに代入した時点で、engineのリファレンスカウンタもnewEngineのものがコピー?されてしまっているってことかな?
[newEngine retain]をもう一つ挟んで、リファレンスカウンタを確認すると、newEngineもengineもカウンタは3になるので、多分合ってる気がする。
- (void)setEngine:(Engine *)newEngine {
[newEngine retain]; // newEngineのリファレンスカウンタは2
[newEngine retain]; // newEngineのリファレンスカウンタは3
[engine release]; // engineのリファレンスカウンタは0
engine = newEngine; // engineのリファレンスカウンタは3、newEngineもリファレンスカウンタは3
}
ちなみにリファレンスカウンタを確認するには、retainCountを使う。
使用例はこんな感じ↓
printf("engine retainCount:%d\n", (int)[engine retainCount]);
engine retainCount:3
#(追記)いただいたコメントを受けて、もう一回カウンタの挙動を確認してみました。
- (void)setEngine:(Engine *)newEngine {
[newEngine retain];
[engine release];
engine = newEngine;
printf("engine retainCount:%d\n", (int)[engine retainCount]); // engineのカウンタは2
printf("newEngine retainCount:%d\n", (int)[newEngine retainCount]); // newEngineのカウンタは2
[engine retain];
printf("engine retainCount:%d\n", (int)[engine retainCount]); // engineのカウンタは3
printf("newEngine retainCount:%d\n", (int)[newEngine retainCount]); // newEngineのカウンタは3
[newEngine retain];
printf("engine retainCount:%d\n", (int)[engine retainCount]); // engineのカウンタは4
printf("newEngine retainCount:%d\n", (int)[newEngine retainCount]); // newEngineのカウンタは4
engineをretainしたりnewEngineをretainするたびにそれぞれのリファレンスカウンタを確認してみたら、おー、同じ値が出てきました。
engine=newEngine の代入式で、両変数が同じリファレンスカウンタ(正確には、同じオブジェクト)を参照していることがわかりました!
tomohisaotaさん、ありがとうございました!