web-dev-qa-db-ja.com

shared_ptrからポインターを切り離しますか?

重複の可能性:
boost :: shared_ptrからポインタを解放する方法は?

私のインターフェースの関数は、オブジェクトへのポインターを返します。ユーザーはそのオブジェクトの所有権を取得することになっています。クライアントにBoostの使用を強制したくないので、Boost.shared_ptrを返したくありません。ただし、内部的には、例外などが発生した場合のメモリリークを防ぐために、共有ポインタにポインタを格納したいと思います。共有ポインタからポインタを切り離す方法はないようです。ここに何かアイデアはありますか?

27
Björn Pollex

探しているのは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を使用 に関するこの質問のディスカッションもご覧ください。

26
James McNellis

常に方法があります:-)

彼らが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();
24
Magnus

ユーザーはそのオブジェクトの所有権を取得することになっています。 Boost.shared_ptrを返したくありません。

shared_ptr共有所有権を表し、インターフェースに転送所有権を表現させます。したがって、std::auto_ptrはここでより適切になります。

ただし、内部的には、例外が発生した場合のメモリリークを防ぐために、ポインタをshared_ptrに格納したいと思います。

繰り返しますが、shared_ptrはその仕事に最適なツールではないかもしれません。例外が発生した場合のリークを防ぐには、scoped_ptrまたはauto_ptrの方が適しています。

11
Éric Malenfant

shared_ptrからscoped_ptrをリソース(shared_ptr<scoped_ptr<Resource>>)に使用します。このようにして、shared_ptrの参照カウントを取得します。これにより、リソースがscoped_ptrに接続されている場合にのみ、リソースが自動的に破棄されます。ただし、所有権を譲渡する準備ができたら、scoped_ptrを切り離すことができます。

4
Ben Voigt

Jamesが十分にカバーしているので、共有ポインタを実際に切り離すことはできません。

内部に複数の所有者が必要ですか、それともクラスからクライアントに所有権を譲渡していますか?その場合、std::auto_ptrが法案に適合する可能性があります。

std::auto_ptrの驚くべきセマンティクスが心配な場合は、boost::scoped_ptrで内部的に保持し、配布した時点で切り離すことができます。手動で削除するか、クライアントに任せてください。独自のスマートポインタに保存します。

あなたの側に複数の所有者がいる場合は、煩わしいカウントを使用できます。内部的にはboost::intrusive__ptrを使用できますが、インターフェイスで生のポインタを渡します。その後、クライアントは参照カウントを手動で操作するか、それをboost::intrusive_ptr自体に保存できます(ただし、クライアントをそれに依存させることはありません)。

2
philsquared