ほとんど一ヶ月ぶりの記事ですね~と。
新しいタグを増やしましたが、仕事の関係でObjective-Cのプログラムをやっていました。
iPhoneあたりにアプリを下ろすためですが・・・。
言語としてはObjective-Cはおもしろいですね。基本にC++があるのでその概念との比較、という形で覚えることができて便利です。
C++というよりはWindowsのCOMに近い(参照カウンタ、インターフェイスの要求など)ものからObjective-Cを考えるようにするとちょっとわかりやすいかも。
ただ、Objective-Cばかりでプログラムをやっていると一つ重大なミスを犯しそうな気がする違いが一つ。
Objective-Cでは、オブジェクトの解放は基本的には次のように書きます。
[_item release]; _item = nil;
このとき、_itemがnil(C++的にはNULL)でもエラーではなく、なにもしない、という流れをくむことになります。
これが、COMオブジェクト(=C++)での解放はこのように書きます。
if(lpItem != NULL){ lpItem->Release(); lpItem = NULL; }
つまり、lpItemがNULLでないことをチェックしないとReleaseの呼び出し時にNULL参照による実行時エラーとなるわけです。
なんかObjective-Cに慣れすぎるとこの辺がバグの温床にもなるような気がしてなりません。
もう一つ、面倒なのが参照カウンタの管理です。はじめやっているとかなり流れに苦しむところだと思います。COMでもそうですが。
参照カウンタは「オブジェクトを確保して初期化する」と自前管理になり、「直接取得する」とautoreleaseで扱われる、というのが一般的です。
つまり、
NSString *str1,*str2; str1 = [NSString stringWithFormat:@"%d",256]; str2 = [[NSString alloc] initWithFormat:@"%d",256];
と書くと、以下のようになります。
str1は「直接取得」とみなされれ、この時点ですでにautoreleaseがかかります。放置しておけば基本的に勝手に解放されます。
str2は「オブジェクトを確保して初期化する」ので、自前管理となり、放置するとメモリリークを起こします。使用後にreleaseを行うか、autoreleaseを行って自動解放するようにします。
・・・わかりづらいったらありゃしない。
違いがわかればそれなりに対応ができるのですが、このautoreleaseというのが微妙にくせ者で、本来は最も内側にあるNSAutoreleasePoolが解放される段階で一緒に解放されるらしいのですが、この「最も内側にある」が特にUIKitを使っているとき(WindowsではMFCを使っているような状況)に不定になるらしく、基本的に「ルーチンを抜けるとすぐにreleaseを発行する」くらいでとらえるのが自然かな~という結論が得られたくらいです。メモリの関係でいつ解放されるのか気が気じゃなかったのですが・・・。(作りすぎてメモリ不足、とかがありそうだった)
C++の時は自前制御なので、悩まずにAddRefを使ったりできるんですけれどね~。
ま、オブジェクトへのメッセージ処理など言語的にはおもしろそうなのでしばらくは仕事にできそうな予感です。