季節は、秋である。
僕は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 が呼ばれ、メモリ解放が行われる。実行結果は以下の通りだ。
[こんにちは]
[さようなら]
もちろん、この手品にはタネがあり、ARCのために導入された構文上の制限を守らねばならないのだが。