季節は、秋である。
僕はRetina MacBook Proを買って以来、iPhone 5を予約したり天国のスティーブジョブズ様に祈りを捧げたりと大忙しで、ブログの更新をサボりがちになっていた。
さて。
そんなAppleの先進的なプロダクトの中核をなす開発言語と言えば、Objective-Cである。
嘗てはC言語の陰に隠れてマイナーなポジションに在った言語であるが、昨今のiPhoe / iPadの普及に伴い、その知名度もようやく上がりつつある。
というわけで、僕もObjective-Cに再挑戦してみようと思い、荻原剛志著『詳解Objective-C 2.0 第3版』なんぞを買ってきて読んで今に至るわけである。
ここから本題であるが、Objective-Cを用いてプログラミングを行う上でネックなポイントが『メモリ管理』であった。この話は去年の3月頃にも一度書いた気がする。
あれから時代は流れ、Objective-Cではメモリ管理を自動化するための ARC (Automatic Reference Counting) という機能が使用できるようになった。もうretainやらreleaseやら手作業でリファレンスカウンタをいじらなくてもよいのだ。
しかし、例えば僕がiPhoneアプリを開発する事になり、UIまわりをObjective-Cで、ロジックをC++でそれぞれコーディングする事にしたとしよう。この場合、UIからロジックにアクセスするために、Objective-C側は何らかの方法でC++側のオブジェクトを参照しておく必要がある。
残念ながらARC は C++ の生ポインタを自動解放してはくれないため、このままではObjective-C側にC++のメモリ解放コードが混在する穢らわしいコードになってしまう。安全性も下がる。たちまちメモリリークが発生し、またたく間にアプリが落ち、やがてApp Storeのレビューには心ないユーザからの罵詈雑言が書き込まれる事だろう。
だが悲観するには早い。
2011年8月12日(僕の誕生日!)に、C++の最新規格であるC++11がISOに承認され、参照カウンタを自動制御できるスマートポインタという仕組みが正式に導入された。
Visual Studioはどうか知らんが、最新のXcode 4.5ではC++11をサポートしている。これでObjective-C、C++ともにメモリ周りにおける懸念がずいぶん軽減された事になる。
しかしながら、ARCはObjective-Cだけの機能であり、スマートポインタはC++だけの機能である。
ここで、一つの疑問が生じた(ほこ×たてっぽく)。
【Objective-CのARCとC++のスマートポインタは共存できるのか】
というわけで、いろいろ実験してみたよー。今日の記事は備忘録的側面が強いので、何言ってるのか分からんという方は読み飛ばして下さい。
1. まずはARCを使ってみる
#import <Foundation/Foundation.h> #import <cstdio> /* 宣言部 */ @interface ObjectiveTercel : NSObject -(id) init; -(void) dealloc; @end /* 実装部 */ @implementation ObjectiveTercel -(id) init { // イニシャライザ self = [super init]; printf("[こんにちは]\n"); return self; } -(void) dealloc { // ファイナライザ printf("[さようなら]\n"); } @end /* main関数 */ int main(int argc, const char * argv[]) { @autoreleasepool { ObjectiveTercel* tercel = [[ObjectiveTercel alloc] init]; } return 0; }
これは適当なクラスを作り、それをインスタンス化するコードである。
main()関数の内部では、インスタンスをポインタ参照している。動的にメモリをアロケートしているため、従来は明示的な解放コードが必要であった。
しかし、上記のコードを実行してみると、@autorelease ブロックを抜けるタイミングで dealloc が呼ばれ、メモリ解放が行われる。実行結果は以下の通りだ。
[こんにちは]
[さようなら]