私のインターフェースの関数は、オブジェクトへのポインターを返します。ユーザーはそのオブジェクトの所有権を取得することになっています。クライアントにBoostの使用を強制したくないので、Boost.shared_ptrを返したくありません。ただし、内部的には、例外などが発生した場合のメモリリークを防ぐために、共有ポインタにポインタを格納したいと思います。共有ポインタからポインタを切り離す方法はないようです。ここに何かアイデアはありますか?
探しているのはrelease
関数です。 shared_ptr
にはリリース機能がありません。 ブーストマニュアルによる :
Q. shared_ptrがrelease()関数を提供しないのはなぜですか?
A. shared_ptrは、unique()でない限り所有権を譲渡できません。これは、他のコピーが引き続きオブジェクトを破壊するためです。
考えてみましょう:
shared_ptr<int> a(new int);
shared_ptr<int> b(a); // a.use_count() == b.use_count() == 2
int * p = a.release();
// Who owns p now? b will still call delete on it in its destructor.
さらに、release()によって返されるポインターは、ソースshared_ptrがカスタム削除機能で作成されている可能性があるため、確実に割り当てを解除するのが困難です。
あなたが考えるかもしれない2つのオプション:
std::tr1::shared_ptr
を使用できます。これにより、ユーザーは、ブーストを使用するためにTR1またはをサポートするC++ライブラリ実装を使用する必要があります。少なくともこれは彼らに2つの間のオプションを与えるでしょう。boost::shared_ptr
のような共有ポインターを実装し、それを外部インターフェースで使用することができます。ライブラリのパブリックインターフェイスでboost :: shared_ptrを使用 に関するこの質問のディスカッションもご覧ください。
常に方法があります:-)
彼らがrelease()メソッドを提供しないのには確かに理由がありますが、それを作成することは不可能ではありません。独自の削除機能を作成します。次の行にあるもの(実際にはコードをコンパイルしていませんが、これは一般的な概念です):
template <typename T>
class release_deleter{
public:
release_deleter() : released_(new some_atomic_bool(false)){}
void release() {released_->set(true);}
void operator()(T* ptr){if(!released_->get()) delete ptr;}
private:
shared_ptr<some_atomic_bool> released_;
}
..
shared_ptr<some_type> ptr(new some_type, release_deleter<some_type>());
..
release_deleter<some_type>* deleter = get_deleter<release_deleter<some_type>>(ptr);
deleter->release();
some_type* released_ptr = ptr.get();
ユーザーはそのオブジェクトの所有権を取得することになっています。 Boost.shared_ptrを返したくありません。
shared_ptr
は共有所有権を表し、インターフェースに転送所有権を表現させます。したがって、std::auto_ptr
はここでより適切になります。
ただし、内部的には、例外が発生した場合のメモリリークを防ぐために、ポインタをshared_ptrに格納したいと思います。
繰り返しますが、shared_ptr
はその仕事に最適なツールではないかもしれません。例外が発生した場合のリークを防ぐには、scoped_ptr
またはauto_ptr
の方が適しています。
shared_ptr
からscoped_ptr
をリソース(shared_ptr<scoped_ptr<Resource>>
)に使用します。このようにして、shared_ptr
の参照カウントを取得します。これにより、リソースがscoped_ptr
に接続されている場合にのみ、リソースが自動的に破棄されます。ただし、所有権を譲渡する準備ができたら、scoped_ptr
を切り離すことができます。
Jamesが十分にカバーしているので、共有ポインタを実際に切り離すことはできません。
内部に複数の所有者が必要ですか、それともクラスからクライアントに所有権を譲渡していますか?その場合、std::auto_ptr
が法案に適合する可能性があります。
std::auto_ptr
の驚くべきセマンティクスが心配な場合は、boost::scoped_ptr
で内部的に保持し、配布した時点で切り離すことができます。手動で削除するか、クライアントに任せてください。独自のスマートポインタに保存します。
あなたの側に複数の所有者がいる場合は、煩わしいカウントを使用できます。内部的にはboost::intrusive__ptr
を使用できますが、インターフェイスで生のポインタを渡します。その後、クライアントは参照カウントを手動で操作するか、それをboost::intrusive_ptr
自体に保存できます(ただし、クライアントをそれに依存させることはありません)。