ほとんどのスマート ポインターは、指しているオブジェクトの所有権を持っています。必要なときにそのオブジェクトを破棄する責任があります。ただし、スマート ポインターが異なれば、所有権のセマンティクスも異なります。つまり、所有権がどのように転送されるか、または転送されないか、オブジェクト間でどのように共有されるか、いつオブジェクトを削除する必要があるかなどを、そのスマート ポインターのユーザーに伝えます。特定のスマート ポインターを使用すると、そのオブジェクトの所有権に関する意図が説明されます。所有権は、他の関数またはオブジェクトに転送できます。
boost::scoped_ptr
非常に厳密な所有権のセマンティクスがあります。所有権の譲渡を一切許可しません。コピー不可にすることでこれを実現します (そのため、別の関数に値で渡すことはできません)。
別の例として、 astd::unique_ptr
もかなり厳密です。その特別な能力は、移動できることです。を右辺値として関数に渡すstd::unique_ptr
と、その関数はオブジェクトの所有権を盗むことができます。オリジナルstd::unique_ptr
はその所有権をすぐに失います。これにより、所有権が 1 つのみに保持されることが保証されstd::unique_ptr
ます。
boost::scoped_ptr
C++11の に相当するのは aconst std::unique_ptr
です。これは、それを作成するとconst
移動が妨げられ、所有権を譲渡できないためです。
所有権のセマンティクスがいかに重要であるかを簡単に確認するには、例を示します。悪意のある開発者のライブラリを使用していて、実装がわからない関数があるとしましょう。たとえば、次のようになります。
cat* foo();
この関数が へのポインタを返すことはご存知でしょうcat
。ただし、これは生のポインターです。delete
ある時点で( を使用して) cat を破棄する必要があるのか、それともライブラリーが代わりに処理してくれるのかはわかりません。オブジェクトが実際に動的に割り当てられたかどうかさえわかりません。ライブラリがまだ を保持しているかどうかはわかりませんcat
。以前は、このような関数がある場合、何をすべきかを見つけるためにドキュメントを調べる必要がありました。ただし、生のポインターに加えてスマート ポインターがあるため、生のポインターには独自の所有権セマンティクスがあり、すべての中で最も緩和されています。cat
「あなたがそれを渡す限り、私がこれを有効に保つことを信じてください。ただし、私が管理します。あまり長く保管しないでください。」
ただし、賢明で親切なライブラリ開発者は、この関数を次のように記述します。
std::unique_ptr<cat> foo();
それで、これはどのように役立ちますか?まあ、多くのstd::unique_ptr
ことを教えてくれます。cat
関数がオブジェクトの所有権を放棄していることを示しています。これcat
はあなたの唯一の責任です。また、それについて考える必要がないため、スマートなポインターを提供するのにも非常に役立ちますdelete
。ポインターを使用するだけで、スコープ外になると、オブジェクトは破棄されます。または、必要に応じて、所有権を別の関数に譲渡できます。
ただし、これは、1 つのポインターだけが所有権を持つという意味ではありませんcat
。誇り高い新しい所有者として、次に何が起こるかを決めるのはあなた次第です. の所有権の共有を開始することを決定することは、完全に合理的ですcat
。
std::unique_ptr<cat> up = foo();
std::shared_ptr<cat> sp(up.release());
賢明で親切なfoo
ライブラリ開発者は、自分の意図が何であるかをあなたに話しただけです。彼女はあなたに を与えcat
、今ではあなたが所有者です。独自の所有権セマンティクスを提供できるようになりました。
このように、aboost::scoped_ptr
は貪欲なcat
買いだめのようなもので、誰とも共有せcat
ず、猫を誰にも渡さず、死ぬまで飼っています。