スマートポインタとは何だろうか。それはポインタのwrapperであり、メモリリークや例外的アクセスを防ぐのに役立つものである。
C++とスマートポインタ
C++11より、スマートポインタの機能が標準ライブラリから使用することが可能になっている。以降、この機能を利用するにはmemoryヘッダをインクルードする必要がある。そして、C++で提供されている主要なスマートポインタは「unique_ptr」と「shared_ptr」である。
unique_ptr
unique_ptrは占有方式のスマートポインタである。つまり、あるリソースの管理を自身のみで行う。複数のインスタンスによる管理を許容しないため、コピーは禁止されている。一方で、ムーブは行うことができる。その際には、ムーブ元の所有権がムーブ先に移り、ムーブ元からはリソースへのアクセスができなくなる。そして、スコープを抜ければリソースは解放される。これはリソースを安全に管理する単純な方法であるが、不便な点が存在する。例えば、サイズの大きなリソースをunique_ptrを用いて管理するとき、そのデータを関数の引数に渡そうとすると、unique_ptrのムーブかリソース自体のコピーを行うしかない。しかし、unique_ptrのムーブをとる場合、関数を抜けた後はそこにリソースの所有権は無い。また、リソース自体のコピーをとる場合、大きな負荷がかかってしまう。
もっとも良い方法は、リソースの参照を渡すことである。しかし、unique_ptrではできない。そこで登場するのが「shared_ptr」である。
shared_ptr
shared_ptrは共有方式のスマートポインタである。これが意味するのは、あるリソースの管理を複数のスマートポインタで行うということである。unique_ptrとは異なり、コピーが許可されている。shared_ptrは参照カウンタにより、リソースの参照を監視している。このカウンタが0となる場合のみ、リソースの解放を行う。欠点は監視のためにパフォーマンスが落ちること、そして循環参照の問題である。循環参照とは、参照先の参照を辿ると巨視的に自分自身への参照となっている参照である。これが起こっているとき、shared_ptrはリソースの解放を行えない。なぜなら、参照カウンタが0になり得ないからである。この問題の解決方法は、「weak_ptr」を利用することである。
weak_ptr
weak_ptrはshared_ptrが管理するリソースの弱参照を提供する。同じリソースへのアクセス権はあるが解放する権利は無い。weak_ptrはshared_ptrの監視外となるから、これを用いれば循環参照の問題を解決できる。その一方で、リソースへアクセスするときはリソースの存在を確認しなければならない。
生ポインタを利用するときはその解放や参照に注意深くなる必要がある一方で、スマートポインタはそれらを任せられる。本筋に集中するためには考えることを減らさなければならない。スマートポインタは効率的にプログラムの品質を高められる重要な機能であるといえよう。実際、近頃話題になっているRustには言語機能としてスマートポインタが組み込まれているようだ。スマートポインタは使いこなしたいものであるだろう。
参考文献