2012年11月18日日曜日

メモリ管理について個人的なまとめ3

今回は解放してはいけないオブジェクトについて。

解放してはいけないオブジェクトというのは、たまに耳にする「コンビニエンスコンストラクタ」から生成されるオブジェクトのことです。

以下説明。

コンビニエンスコンストラクタで生成されたオブジェクトはallocメソッドとそのクラスに対応するinitメソッド、さらにautoreleseメソッドを付加したオブジェクトを返すので、releaseは必要ありません。もしreleseすると怒られます。

ちなみに、コンビニエンスコンストラクタは一時的なインスタンスを生成するクラスメソッドのことで、「ファクトリーメソッド」などとも言われるそうです(詳解 Objective-C 2.0 第3版 P.82)。

コンビニコンストラクタたち

コンビニコンストラクタたちってどんな子たちなの?という方は以下をご覧ください。

NSString
  • string
  • stringWith~

NSArray (NSMutableArray)
  • array
  • arrayWith~

NSData (NSMutableData)
  • data

NSDictionary (NSMutableDictionary)
  • dictionary
  • dictionaryWith~

NSNumber (NSMutableNumber)
  • numberWith~

ネーミングルールとして「プレフィックス(NS)を取ったクラスの名前」か「プレフィックス(NS)を取ったクラスの名前 + With~」で始まっているメソッドですね。この「With~」の前にinitが付くとこれはreleseが必要なメソッドになるので注意です。

他にもあると思うので、Foundationフレームワークの資料なんかを見て他にもあるのか探してみてもいいかもしれません。

簡単な例

コンビニコンストラクタのオブジェクトの解放について簡単な例を二つほど。

(a)

NSString *str = [NSString stringWithFormat:@"%@", @"あああ"];
//[str release];  // コンビニコンストラクタであるためreleaseは不要

(b)

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *str1 = [NSString stringWithFormat:@"%@", @"あああ"];  // (1)
NSString *str2 = [[[NSString alloc]init]autorelease];  // (2)
[pool release];

(a)はコメントを参照してください。
(b)の説明だけを以下に書きます。

上で説明したように、(1)コンビニコンストラクタはautoreleseメソッドを付加したオブジェクトを返します。また(2)もautoreleaseメッセージが送られています。よって(1)、(2)共にループ終了時にオブジェクトが解放されます。

おわり

もしコンビニコンストラクタで生成されたオブジェクトをどこかで使いたいそのオブジェクトをcopyまたはretainするようにすればいいようです。

参考記事

releaseの使いどころ - As Sloth As Possible
隠れAutoreleaseオブジェクト - うたブログ~情報編

0 件のコメント:

コメントを投稿