shared_ptrを使ってみた
スマートポインタのうちshared_ptrの使い方を確かめてみた。
shared_ptr
前回はunique_ptrを使ってみた。 今回はshared_ptr。
unique_ptrはrelease()してポインタの所有権を放棄しないと他の変数に代入できなかった。たった1つだけが所有することで、解放のタイミングもわかりやすかった。
しかし、shared_ptrはいくつでも代入できる。 他から参照されてもかまわない。 なにせsharedだから、共有するのが本分。
shared_ptrは皆から参照がされなくなったとき、解放される。
参照されている数はuse_count()
で取得できる。
循環参照
shared_ptrが互いに互いを参照してしまったとき、解放されないことになってしまう。 循環参照という問題らしい。メモリリークしてしまう。
weak_ptr
そこで、所有権をもたないスマートポインタweak_ptr
を使う。
使い分け
ポインタ | 解放 |
---|---|
生ポインタ | 解放はdelete構文を使って手動でやる |
スマートポインタ | スマートポインタ変数が定めたタイミングでアドレス先を解放する |
スマートポインタは生ポインタより以下の強みがある。
- 解放し忘れを防げる
- 解放処理を指定できる
- アドレスを渡すか否かを制御できる
- 解放タイミングを制御できる
スマートポインタ | ポインタの扱い |
---|---|
unique_ptr | 誰にも渡さない |
shared_ptr | みんなでシェア |
weak_ptr | shared_ptrのポインタを所有することなく見る |
unique_ptr
unique_ptrは、他のポインタ変数とアドレスを共有しない。 自分だけがそのアドレスを保持する唯一のポインタ変数である。
メリット
自身のメモリが解放されるときにアドレス先を解放する。
デメリット
所有権を放棄するかswapしないかぎり、ほかのポインタ変数に代入できない。
shared_ptr
shared_ptrは、他のポインタ変数とアドレスを共有できる。 そのアドレスを参照する変数がなくなったとき、アドレス先は解放される。
メリット
複数のポインタ変数から参照できる。
デメリット
shared_ptr同士だと循環参照がおきて解放できずメモリリークする可能性がある。 循環参照せぬよう所有権をもたないweak_ptrとの併用が必要。
実践での予想
実践ともなるとまた違った技術が必要になりそう。
WindowsAPIとかはいろいろとHANDLEとかのGet/Releaseが多い。 これをスマートポインタでやるとなると特殊な記述が必要になりそう。 Get/Releaseの関数の組み合わせ分だけ、カスタムdeleterをつくる羽目になるのか。
http://d.hatena.ne.jp/nagoya313/20100305/1267758837
デザインパターンでいうところのRAIIというらしい。 かっこいいし、安全そうだけど、そこまでやる必要があるのか判断できない。 WindowsAPIの全オブジェクトに対してやっていたらキリがなさそうな気がする。
所感
こんなに細かく考えないとポインタが使えないという時点で、ポインタを使いたくなくなる。 もともと使いたくないけど、使わねば実現できないことも多い。
値型と参照型だけでやれたら楽だろうな。