質問: こんばんは、趣味で C++ でゲームプログラミングをしている者です。 現在 C++ でポインタを扱う際には生のポインタを扱うことは相応しくないと聞き、unique_ptr, shared_ptr, weak_ptr などのスマートポインタについて学習しました。 スマートポインタにより delete を書かなくてよくなりメモリリークの心配が減りました。 しかしながら記述する量が増えてしまい(例えば Sprite* sprite ではなく std::shared_ptr sprite)、コードが読みづらくなってしまいました。 例えば生のポインタを使った場合、 ``` class SpriteList { public: void addSprite(Sprite* sprite); Sprite* getSprite(int index); private: std::vector spriteList_; }; ``` 程度の記述で十分なのに、スマートポインタを使った場合には、 ``` class SpriteList { public: void addSprite(std::shared_ptr sprite); std::shared_ptr getSprite(int index); private: std::vector> spriteList_; }; ``` と、長い記述が必要になってしまいました。 using などを使えば短く書くことはできるとは思うのですが、これは仕方のないことなのでしょうか。 スマートポインタを活用して書かれたコードを見たことがないため、いまいち正しい使い方が分かっておりません。 例えばスマートポインタに対する Getter/Setter の引数や戻り値にもスマートポインタを使うべきなのでしょうか? 上にお示ししたスマートポインタのコードではそのようにしたのですが、例えば、 ``` class SpriteList { public: void addSprite(Sprite* sprite); Sprite* getSprite(int index); private: std::vector> spriteList_; }; ``` のようにしてあげれば冗長な記述が不要となる気もしました。
回答: > > using などを使えば短く書くことはできるとは思うのですが、これは仕方のないことなのでしょうか。 > > > これはしょうがいないですね。usingを使いましょう。 > > 例えばスマートポインタに対する Getter/Setter の引数や戻り値にもスマートポインタを使うべきなのでしょうか? > > > 正当な理由がない限りは使うべきです。 > > のようにしてあげれば冗長な記述が不要となる気もしました。 > > > ``` Sprite* getSprite(int index); ``` 例えば上記で受け取ったポインタをSpriteListのインスタンスが破棄されたあとに 使用すると不正なメモリにアクセスすることになります。 SpriteListクラスを使用するプログラマは上記を常に意識しなければいけません。 shared_ptrもしくはweak_ptrで返却してあげれば、その心配がありません。 追記 weak_ptrについてコメントをいただいたので追記します。 weak_ptrはsahred_ptrが必ず取得できるわけではありません。 ですので、通常は以下のように使います。 ``` auto shared = weakptr.lock();//shared_ptr<>を取得 if(shared){//使えるか確認 shared->render();//使う。 //shared_ptrで参照カウントがカウントアップされているので安全に使える。 } ``` 以下はダメな例です。 ``` if(weakptr.lock()){ weakptr.lock()->render();//危ない!! } ``` 最初のロックと2回目のロックの間にweakptrで監視しているshared_ptrが破棄されている場合があります。