C++のオブジェクトをポインタとして保持/管理する方法【Objective-C++】

C++のクラス・オブジェクトをポインタ/スマートポインタ形式のインスタンス変数として管理する方法を紹介します。

Objective-C++では、ポインタではない通常のC++オブジェクト・インスタンス変数を保持することも可能ですが(参考: C++のクラスや資産をObjective-Cで活用する【ラップ方法とライフサイクルについて】)、C++クラスの特定のコンストラクタを明示的に呼び出す必要がある場合には、今回紹介する方法が必要となる場合があります。

目次

ポインタによるC++オブジェクトの管理

C++クラス型のインスタンス変数をポインタとして宣言する場合は、C++オブジェクトの初期化と解放をイニシャライザ側で手動で行う必要があります。

/* C++ */
struct Cpp {
  void print() { puts("Hello C++"); }
};

/* Objective-C++ */
@implementation ObjCpp {
  Cpp *_cpp; // C++オブジェクト・ポインタ
}

// 初期化(イニシャライザ)
- (instancetype)init {
  if (self = [super init]) {
    _cpp = new Cpp(); // C++オブジェクトを初期化
  }
  return self;
}

// 解放(デアロケータ)
- (void)dealloc {
  delete _cpp; // C++オブジェクトを解放
}

- (void)print {
  _cpp->print(); // "Hello C++"
}
@end

スマートポインタを保持する場合

ポインタの代わりにスマートポインタを利用すると、先程のデアロケータによるオブジェクト・ポインタへの明示的な解放処理が不要になります。

@implementation ObjCppSmartPtr {
  std::unique_ptr<Cpp> _cpp;
}

- (instancetype)init {
  if (self = [super init]) {
    _cpp = std::make_unique<Cpp>();
  }
  return self;
}

- (void)print {
  _cpp->print();
}
@end

Objective-C側のインスタンスが解放されると、自動的にunique_ptr側のデストラクタが呼び出されるためです。deleteによるメモリ解放はunique_ptr側が行ってくれます。

C++のインスタンスが複数のObjective-Cクラスから参照されるようなケースでは、shared_ptrの利用が便利です。Objective-Cにおける__strong修飾された変数に相当するものを実現できます。弱参照を利用する際にはweak_ptrを活用すると良いでしょう。

@implementation ObjCppSmartPtr {
  std::unique_ptr<Cpp> _strong_obj; /* 強参照 */
  std::weak_ptr<Cpp>   _weak_obj;   /* 弱参照 */
}

// ARCとの互換性はないためこちらの方法は使用できない
@implementation ObjCppARC {
  // ARCはC++オブジェクトには対応していない
  __strong Cpp *_strong_obj; // 警告: '__strong' only applies to Objective-C object or block pointer types; type here is 'Cpp*'
  __weak   Cpp *_weak_obj;   // 警告: '__weak' only applies to Objective-C object or block pointer types; type here is 'Cpp*'
}
広告