Entries

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

C++から見たObjective-C - オブジェクトの所有権

タグ: C++ Objective-C

Cocoaのオブジェクトは「参照カウンタ」によって所有権管理を行う。
(Objective-C 2.0にはガベージコレクタもあるが、使ったことがないので今回は無視)

id obj = [[NSString alloc] initWithString:@"Hoge"]; // alloc により参照カウンタ=1
[obj retain]; // retain により参照カウンタ=2
[obj release]; // release により参照カウンタ=1
[obj release]; // 参照カウンタ=0 となり dealloc が呼ばれ、オブジェクトは破壊される

このような単純な例では、alloc retain releaseは
alloc回数(必ず1) + retain回数 = release回数
となるので分かりやすい。

しかし実際に使う場合、これだけでは何かと面倒が多い。
例えばこのようなメソッドがあった場合、

- (NSString*)string

これは必ず「呼び出し側が戻り値をreleaseしなければならないメソッド」として実装しなければならない。
例え、このメソッドを持つオブジェクトが戻り値に対する所有権を持っていたとしても、オブジェクトをretainしてから返す。
そうしておかないと、「戻り値をreleaseしなければならないメソッド」と「戻り値をreleaseしてはならないメソッド」が混在して、ややこしいことになる。

で、releaseしなければならないということは、

NSLog("%@", [hoge string]);

こう書くことはできず、「一時保存」「処理」「解放」のため、処理を3行に分けて記述しなければならないということだ。

NSString* string = [hoge string]; // 一時保存
NSLog(@"%@", string); // 処理
[string release]; // 解放

これが地味に面倒だったりする。

このような手間を省くため、Cocoaのクラスにはもう一つ、所有権管理用のメソッドとしてautoreleaseが用意されている。

id obj = [NSString stringWithString:@"Hoge"]; // クラスメソッドにより参照カウンタ=1 + autorelease
[obj retain]; // retain により参照カウンタ=2 + autorelease
[obj release]; // release により参照カウンタ=1 + autorelease
// 以降、objが格納されているautorelease poolが破壊されたタイミングでreleaseが呼ばれる

autoreleaseの存在により、Cocoaには「allocで始まる名前のメソッド以外が返す戻り値はreleaseしてはならない(≒autoreleaseされている)」というルールが成立している。
よって、先ほどの

- (NSString*)string

の戻り値は、Cocoaでは「戻り値をreleaseしてはいけないメソッド」として実装する。

C++の場合、現標準ではろくな所有権管理機能がない(std::auto_ptrはそこそこ便利だが)ので、ここは素直にBoostTR1を使う。

boost::shared_ptr<std::string> str1(new std::string("Hoge")); // newされたオブジェクトを参照数=1で管理開始
{
	boost::shared_ptr<std::string> str2(str); // str2のコンストラクタにより参照数が2に
} // str2のデストラクタにより参照数が1に
// 以降、str1が破壊されるタイミングでデストラクタが働き参照数0となり、deleteが呼ばれる

特に理由がなければ、C++では生のポインタは所有権を持たない「弱い参照」としてのみ扱い、所有権を持つ「強い参照」はスマートポインタで扱った方が良いだろう。
「解放処理を呼ばなければならない生ポインタ」の存在は、autoreleaseがない時のstringメソッドの例同様、「解放処理を呼んではならない生ポインタ」との共存によりややこしいことになる。

スポンサーサイト

コメント

コメントの投稿

コメントの投稿
管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://idlysphere.blog66.fc2.com/tb.php/120-39f867e3
この記事にトラックバックする(FC2ブログユーザー)

Appendix

タグ

Blog内検索

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。