2011年2月5日土曜日

Objective-C(メモリ管理方式)

カウンタ管理方式とガベージコレクション

Objective-Cはメモリ管理方式として、
  • カウンタ管理方式
  • ガベージコレクション
が用意されています。
カウンタ管理方式はオブジェクトの参照カウンタにより、最終的にオブジェクトへの参照が無くなってからメモリを開放する方式です。但し、カウンタの操作はプログラマが行う必要があります。
ガベージコレクションは簡単に言うと不要になったオブジェクトを探し出し、自動的に開放してくれるシステムです。Java等はガベージコレクションが採用されていると思います。ガベージコレクションと言っても、様々な実装方式があり、細かいことは省略したいと思います。

iOS4のメモリ管理方式

なんと、個人的には驚いたのですが、iOS4のメモリ管理方式としては「カウンタ管理方式」しか提供されていないとのこと。iOS4でガベージコレクションは利用出来ないのです。

リファレンスカウンタの操作

リファレンスカウンタの操作には以下の3つのメソッドが提供されており、NSObjectクラスにて定義されています。

メソッド名説明
- (id) retain リファレンスカウンタをインクリメント
- (oneway void) release リファレンスカウンタをデクリメント
- (void) dealloc メモリ開放時に呼ばれるメソッド

以下、サンプルコード。

#import 
#import 

@class B;

//Class A
@interface A : NSObject{
  B* bInstance;
}
- (id) init;
- (void) dealloc;
- (void) bInstance: (B*) inst;

@end

@implementation A
//初期化メソッド
- (id) init {
  self = [super init];
  bInstance = nil;
  return self;
}

//メモリ解放時に呼び出されるメソッド
- (void) dealloc {
  printf("class A : dealloc called.\n"); 
  if (bInstance != nil) {
    //クラスA自体が開放されるため、保持しているインスタンス変数の
    //リファレンスカウンタデクリメントを行う
    [bInstance release]; //リファレンスカウンタをデクリメント
  }
  //必ず呼び出す必要がある
  [super dealloc];
}

//クラスAのインスタンス変数にクラスBのインスタンスを設定
- (void) bInstance: (B*) inst {
  bInstance = inst;
}
@end

//Class B
@interface B : NSObject {
}
- (id) init;
- (void) dealloc;

@end;

@implementation B
- (id) init {
  self = [super init];
  return self;
}

- (void) dealloc {
  printf("class B : dealloc called.\n");
  [super dealloc];
}
@end;

//main
int main(void) {
  A *aInstance = [[A alloc] init]; //インスタンスA生成
  B *bInstance = [[B alloc] init]; //インスタンスB生成

  //クラスAのインスタンス変数にクラスBのインスタンスを設定
  //クラスBのリファレンスカウンタをインクリメントしてから受け渡す
  [aInstance bInstance: [bInstance retain]]; 

  [aInstance release]; //リファレンスカウンタデクリメント
  [bInstance release]; //リファレンスカウンタデクリメント
  return 0;
}

実行結果
class A : dealloc called.
class B : dealloc called.

0 件のコメント :

コメントを投稿