CHAPTER05 リファレンスカウンタを用いたメモリ管理方式
2011/09/04(日) 22:41 Objective-C親記事へこのエントリーをはてなブックマークに追加

CHAPTER05 リファレンスカウンタを用いたメモリ管理方式

リファレンスカウンタ

Objective-Cでは参照カウンタを使ったメモリ管理をする。
インスタンスにretainを送ってインスタンスを保持したりする。
retainを送ることによってインスタンスを保持している状態を、インスタンスに対する「オーナーシップを持っている」という。
ただし、このオーナーという概念はObjective-C仕様には存在しない。

インスタンスの開放のためのメソッド定義

オーナーシップを放棄するためにはオブジェクトに対してrelaseを送りますが、、基本的にはdeallocメソッドをオーバーライドしてreleaseをします。
あるクラスのインスタンスを解放する = そのインスタンスが保持していたオブジェクトのオーナーシップを放棄する
ということになる。

自動開放の仕組み

CocoaのObjective-CにはNSAutoreleasePoolというクラスを使った自動開放の仕組みがある。
//プール作成
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

//たくさんのオブジェクトを登録

//プール破棄時に、登録したオブジェクトにreleaseが送信される
[pool release];
pool releaseで、登録したオブジェクトに対してひとつづつreleaseが実行される感じ。
使い道として、ループ処理の前後に挟んでやるとか(ただ、breakなどするとあぼん)
もう一つはGUIを使ったアプリで、マウスキーボードを監視して対応したメソッドを呼ぶ感じの実行ループの時に使うなど。

オーナーシップポリシー

オーナーシップポリシーとは「インスタンスオブジェクトのオーナーが、そのインスタンスの開放に関して正規人を持つ」ということににする取り決め。

オブジェクトが別のオブジェクトのオーナーになるとはどういう場面?
allocによるインスタンス生成
クラスに対してallocする、newなどでインスタンスを生成した場合、メッセージを送ったオブジェクトが新しく生成されたインスタンスのオーナーになります。
copyによるインスタンスのコピー
copy系のメソッドで、インスタンの複製を生成した場合、メッセージを送ったオブジェクトが、新しく複製されたインスタンスのオーナーとなる
retainによる保持
あるインスタンスにretainメッセージを送って保持した場合。
メッセージを送ったオブジェクトが、レシーバであるインスタンスのオーナーとなる。
つまり、一つのインスタンスに対して、複数のオブジェクトがオーナーとなることができる。
= インスタンスの共有
インスタンスのオーナーがreleaseやautoreleaseをするのは当然だが、逆にそれ以外のオブジェクトがreleaseすることは原則禁止。

メッセージの送受信とオーナーシップ

メッセージの引数にオブジェクトを送る、返り値がオブジェクトの場合について。
基本的にはオーナーシップの移動は起きないものとする。
渡した先でretainによる保持を行う事は自由に行える。
逆にインスタンスを渡す側がそのインスタンスを使わないからautoreleaseしてオーナーシップを放棄してから渡すという事がある。
この2つが同時に起こるとオーナーシップが移譲されたように見えてしまうのが混乱の元。
- (id)temValue{
	id tmp = [[ComplexData alloc] init] initWithData:myValue];
	return tmp;
}
このようなメソッドの場合、メソッドの実行が終了した時点で、生成されたインスタンスにはオーナーがあに。メソッドの呼び出し側がretainしたとき呼び出し側がオーナーとなるが、何もしなければ自然消滅する。

一時的なインスタンスを生成するクラスメソッドをObjective-Cではコンビニエンスコンストラクタという。
allocとinit、autoreleaseを呼び出してインスタンスを返すようなクラスメソッドの事。

開放しないオブジェクト

NSString文字列のようなオブジェクト定数の事。
これらのオブジェクトにretainCOuntのメッセージを送るとUINT_MAXという値が帰ってくる。
開放したくないオブジェクトを定義するには、クラス定義でretain,release、retainCountを書き換える必要があり、これらのメソッドのsuperも呼び出さないようにする。
そして、retainCountが常にUINT_MAXを返すようにする。
これを使うのはシングルトンぐらいで、シングルトンはsharedから始まるクラスメソッドを持っていて共有される唯一のインスタンスを返すように実装されるためである。

名前:  非公開コメント   

  • TB-URL  http://efcl.info/adiary/0130/tb/