ポインタをshared_ptrから切り離しますか?[重複]
-
11-09-2019 - |
質問
私のインターフェースの関数はオブジェクトへのポインターを返します。ユーザーはそのオブジェクトの所有権を取得する必要があります。クライアントにブーストの使用を強制したくないので、Boost.shared_ptr を返したくありません。ただし、内部的には、例外などの場合のメモリリークを防ぐために、ポインタをshared_ptrに保存したいと考えています。共有ポインタからポインタを切り離す方法はないようです。何かアイデアはありますか?
解決
あなたが探しているのは、 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.
さらに、ソースのshared_ptrがカスタムデリータを使用して作成されている可能性があるため、release()によって返されるポインタを確実に割り当て解除することは困難です。
検討できる 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
彼ら自身(しかし、あなたは彼らをそれに依存させてはいけません)