31

Possible Duplicate:
How to release pointer from boost::shared_ptr?

A function of my interface returns a pointer to an object. The user is supposed to take ownership of that object. I do not want to return a Boost.shared_ptr, because I do not want to force clients to use boost. Internally however, I would like to store the pointer in a shared_ptr to prevent memory leaks in case of exceptions etc. There seems to be no way to detach a pointer from a shared pointer. Any ideas here?

4

5 に答える 5

27

あなたが探しているのはrelease関数です。shared_ptrリリース機能はありません。 Boostマニュアルによると

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 ++ライブラリ実装を使用する、Boostを使用する必要があります。少なくともこれは彼らに2つの間のオプションを与えるでしょう。
  • boost::shared_ptr独自の共有ポインタのようなものを実装して、それを外部インターフェイスで使用することができます。

ライブラリのパブリックインターフェイスでのboost::shared_ptrの使用に関するこの質問の説明もご覧ください。

于 2009-12-02T14:52:02.830 に答える
25

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

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();
于 2011-05-13T17:45:40.383 に答える
11

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

shared_ptr所有権の共有を表現し、インターフェイスで所有権の譲渡を表現する必要があります。std::auto_ptrしたがって、ここではより適切です。

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

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

于 2009-12-02T15:07:06.217 に答える
6

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

于 2011-09-29T22:40:13.427 に答える
2

James がよく説明しているように、共有ポインタを実際にデタッチすることはできません。

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

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

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

于 2009-12-02T15:06:39.933 に答える