読者です 読者をやめる 読者になる 読者になる

ぷろみん

プログラミング的な内容を扱ってます

shared_ptrとunique_ptrとweak_ptr

モチベーション

スマートポインタの使い方を勘違いしている方が多いので

スマートポインタの意味

スマートポインタの一番重要な所はポインタに意味付けする事ができる事にあります。

shared_ptrは共有するポインタである事を示し
unique_ptrは自分で開放する事を示し
weak_ptrは開放する責任が無い事を示しています。

shared_ptr

注意すべきポイントは、shared_ptr自体はまず共有してはいけない所です。 なぜならshared_ptrを渡すという事は開放の責任を他の人に渡す事に他ならないからです。つまり、プログラマーが開放を管理できなくなります。

例えば、FooManagerというクラスがshared_ptrを渡してしまった時、開放の責任は渡したクラスにも移ってしまうので、FooManagerが開放された際にFooは開放されず、何にもマネージできていないFooManagerとなってしまいます。

他のクラスに渡す場合にはweak_ptrを使いましょう。

weak_ptr

weak_ptrは開放の責任を負わないshared_ptrです。つまり、weak_ptrを渡されたクラスはshared_ptrを保有しているクラスが開放されようが、自分が先に開放されようが問題ありません。

つまり、一番汎用性があり、一番使われるべきスマートポインタは実はweak_ptrなのです。循環参照を防ぐ為のポインタでは無いのです。

unique_ptr

unique_ptrはコピーができません。つまり明示的に他のクラスに渡すのを禁止しているのです。つまりunique_ptrを見たらここで開放されるというのが明らかに分かるのです。

まとめ

shared_ptrを見かけたら(普通)所持しているクラスが開放して、他のクラスにweak_ptrを渡すという事を期待します。

weak_ptrを見かけたら、他のクラスからポインタを受け取る事を期待します。

unique_ptrを見かけたら他のクラスの事を気にする必要がない事を期待します。

管理元を委託したいという特殊な場合に限りshared_ptrを渡すという選択肢が出てきます。shared_ptrを複数のクラスが保持し続けるのは良くない傾向です。

ただ、これにも例外があって開放に依存関係の無いクラスに限ってはどんどんshareしても問題ありません。ただ、この用法だとsahared_ptrが散乱して上記の用途の物と混ざってshared_ptrを見てもどっちの用途だか分かりません。こちら用の専用のポインタがあると良いのですが。

流石に盛りすぎた感はあります。ガベージコレクションとしてのshared_ptr運用の方が無効なオブジェクトの管理という煩わしさが無く、良い面も多いです。ただ、使うべきでは無いタイミングは明確にあります。