LoginSignup
6
6

More than 5 years have passed since last update.

cocos2d-x で Sprite とかを shared_ptr や unique_ptr でも扱う。

Posted at

みなさん、おはにちばんは。
いきなりですが、cocos2d-x 管理下に置かれたアイツらを STL のスマートポインタで扱いたくないですか。1
retain, release を呼び出すのめんどくさいし、良くミスしますからね。
というわけで、shared_ptr 及び unique_ptr でうまく扱えるようにする方法を書きたいと思います。

shared_ptr で扱う

まずは shared_ptr で扱えるようにしてみたいと思います。
shared_ptr には Deleter をコンストラクタで指定することができるので、
create 関数で生成したポインタを shared_ptr に包み込む関数を作ればうまくいくはずです。

template <typename T>
std::shared_ptr<T> make_shared_cocos(T *ptr)
{
    ptr->retain();
    return std::shared_ptr<T>(ptr, [](T *qtr) { qtr->release(); });
}

やっていることは、shared_ptr を作成する直前に retain を 1 回呼び出して、
すべての shared_ptr が破棄されたときに release を 1 回呼び出しています。

使い方は以下のようにします。

std::shared_ptr<cocos2d::Sprite> sharedSprite = make_shared_cocos(Sprite::create("hoge.png"));

これで cocos2d-x のメモリ管理下でも shared_ptr を使えるようになりました。
注意点としては、これによって cocos2d-x 側で持っている参照カウントが当てにならなくなります。
getReferenceCount の値によって挙動を変える処理をしている場合は注意してください。

unique_ptr

次は unique_ptr を使えるようにしてみましょう。2
unique_ptr は shared_ptr と違い、Deleter をクラスのテンプレート引数に指定する方式になっています。
毎回 Deletor を指定するのはミスしそうですし、ついでにエイリアスも作っちゃいましょう。

struct cocos_deleter
{
    void operator()(cocos2d::Ref *ptr)
    {
        ptr->release();
    }
};

template <typename T>
using unique_cocos_ptr = std::unique_ptr<T, cocos_deleter>;

template <typename T>
unique_cocos_ptr<T> make_unique_cocos(T *ptr)
{
    ptr->retain();
    return unique_cocos_ptr<T>(ptr);
}

やっていることは、unique_ptr の Deleter に cocos_deleter というものを使用させるようにしています。
cocos_deleter には、unique_ptr が破棄された時に release を呼び出すようにお願いしています。
shared_ptr と同じように扱えるようにするため、make_unique_cocos というものも定義しています。

使い方は以下のようになります。

unique_cocos_ptr<Sprite*> uniqueSprite = make_unique_cocos(Sprite::create("hoge.png"));

これで cocos2d-x のメモリ管理下でも unique_ptr を使えるようになりました。
注意点としては、shared_ptr と同じく cocos2d-x 側で持っている参照カウントが当てにならなくなります。
あと、std::unique_ptr<Sprite*> と使うことはできないので注意してください。

最後に

いかがでしたでしょうか。
これでいい感じに shared_ptr, unique_ptr でメモリ管理できているのではないでしょうか。
それでは。



  1. 書いた後に cocos2d::RefPtr なるものを知りましたが、最新のリファレンスにも載ってないし、微妙そう。 

  2. たいていの場合 addChild とかしちゃうから unique じゃないだろうっていう感じはしますが、オブジェクトプールする時のためやパフォーマンスのためだと考えればアリ? 

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6