Reference Count

Cocoa の参照計数が気になったのでサンプルコードを書いて確認してみる。

#import <Foundation/Foundation.h>

@interface A : NSObject
-(void)dealloc;
@end

@implementation A
-(void)dealloc
{
  NSLog(@"A retainCount before [super dealloc]: %d\n", [self retainCount]);
  [super dealloc];
}
@end

int main (int argc, const char * argv[])
{
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  A *anObject = [[A alloc] init];
  NSString *aString = [NSString stringWithString: @"this is not a string\n"];
  NSString *aString2 = [NSString stringWithUTF8String: "this is an UTF8 string\n"];
  NSString *aString3 = [[NSString alloc] initWithString: @"this is a string\n"];
  NSArray *anArray = [NSArray arrayWithObjects: @"A", @"B", nil];
  NSArray *anArray2 = [[NSArray alloc] initWithObjects: @"C", @"D", nil];
  NSMutableArray *ownerArray = [NSMutableArray array];

  NSLog(@"anObject retainCount: %d\n", [anObject retainCount]);      // --> 1
     // alloc init した直後の参照カウンタは 1
  NSLog(@"anObject autorelease\n");
  [anObject autorelease];
  NSLog(@"anObject retainCount: %d\n", [anObject retainCount]);      // --> 1
     // autorelease しても 1
  NSLog(@"aString retainCount: %d\n", [aString retainCount]);        // --> 2147483647
     // stringWithString では不変オブジェクトになった
  NSLog(@"aString2 retainCount: %d\n", [aString2 retainCount]);      // --> 1
     // stringWithUTF8String では通常のオブジェクト
  NSLog(@"aString3 retainCount: %d\n", [aString3 retainCount]);      // --> 2147483647
     // initWithString では不変オブジェクトになった
  NSLog(@"anArray retainCount: %d\n", [anArray retainCount]);        // --> 1
     // コンビニエンスコンストラクタでは 1
  NSLog(@"anArray2 retainCount: %d\n", [anArray2 retainCount]);      // --> 1
     // 通常の初期化メソッドでも 1
  [ownerArray addObject: aString2];
  NSLog(@"aString2 retainCount: %d\n", [aString2 retainCount]);      // --> 2
     // コンテナに格納すると参照計数が上がる
  [ownerArray removeObject: aString2];
  NSLog(@"aString2 retainCount: %d\n", [aString2 retainCount]);      // --> 1
     // コンテナから削除すると参照計数は下がる
  [pool drain]; // --> A retainCount before [super dealloc]: 1
     // 自動解放プールから解放される時は参照カウンタが 1 の時
     // これは自動解放プールのみが所有しており他からは参照されていないということを表しているのか
  return 0;
}

基本的にインスタンスを生成した時は retainCount は 1 。通常自動変数に代入するので、自動変数が所有権を持っていると考えればよいか。