77

私はboost:shared_ptr自分のコードで広範囲に使用しています。実際、ヒープに割り当てられているオブジェクトのほとんどは、によって保持されていshared_ptrます。this残念ながら、これは、をとる関数に渡すことができないことを意味しshared_ptrます。このコードを考えてみましょう:

void bar(boost::shared_ptr<Foo> pFoo)
{
    ...
}

void Foo::someFunction()
{
    bar(this);
}

ここには2つの問題があります。shared_ptrまず、のT *コンストラクターが明示的であるため、これはコンパイルされません。次に、それを強制的にビルドするとbar(boost::shared_ptr<Foo>(this))、オブジェクトへの2番目の共有ポインターが作成され、最終的には二重削除になります。

これは私の質問に私をもたらします:あなたが知っている既存の共有ポインタのコピーをそれらのオブジェクトの1つのメソッドの内部から取得するための標準的なパターンはありますか?ここでの唯一のオプションは、侵入参照カウントを使用していますか?

4

6 に答える 6

102

enable_shared_from_thisから派生し、「this」の代わりに「shared_from_this()」を使用して、自分の自己オブジェクトへの共有ポインターを生成できます。

リンクの例:

#include <boost/enable_shared_from_this.hpp>

class Y: public boost::enable_shared_from_this<Y>
{
public:

    shared_ptr<Y> f()
    {
        return shared_from_this();
    }
}

int main()
{
    shared_ptr<Y> p(new Y);
    shared_ptr<Y> q = p->f();
    assert(p == q);
    assert(!(p < q || q < p)); // p and q must share ownership
}

メンバー関数からスレッドを生成して、thisではなくshared_from_this()にboost::bindすることをお勧めします。オブジェクトが解放されないようにします。

于 2008-09-26T22:46:57.667 に答える
19

shared_ptrの代わりに、関数パラメーターにrawポインターを使用するだけです。スマートポインタの目的はオブジェクトの存続期間を制御することですが、オブジェクトの存続期間はC++スコープルールによってすでに保証されています。少なくとも関数の終わりまで存在します。つまり、呼び出し元のコードは、関数が戻る前にオブジェクトを削除できない可能性があります。したがって、関数内のオブジェクトを削除しようとしない限り、「ダム」ポインタの安全性が保証されます。

shared_ptrを関数に渡す必要があるのは、オブジェクトの所有権を関数に渡す場合、または関数にポインターのコピーを作成させる場合のみです。

于 2008-09-27T03:59:49.520 に答える
14

boostにはこのユースケースの解決策があります。enable_shared_from_thisを確認してください

于 2008-09-26T22:44:53.443 に答える
9

バー内で pFoo の共有コピーを作成していますか? 内部でクレイジーなことをしていない場合は、次のようにします。


void bar(Foo &foo)
{
    // ...
}
于 2008-09-26T23:07:06.260 に答える
5

C++11 では標準ライブラリに含まれていますshared_ptrenable_shared_from_this後者は、名前が示すように、まさにこの場合です。

http://en.cppreference.com/w/cpp/memory/shared_ptr

http://en.cppreference.com/w/cpp/memory/enable_shared_from_this

例は、上記のリンクに基づいています。

struct Good: std::enable_shared_from_this<Good>{
    std::shared_ptr<Good> getptr() {
        return shared_from_this();
    }
};

使用する:

std::shared_ptr<Good> gp1(new Good);
std::shared_ptr<Good> gp2 = gp1->getptr();
std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';
于 2012-12-25T13:08:42.610 に答える
3

ポインターを受け取る関数は、次の 2 つの動作のいずれかを実行します。

  • 渡されたオブジェクトを所有し、スコープ外になると削除します。この場合、X* を受け入れるだけですぐにそのオブジェクトを (関数本体で) scoped_ptr でラップできます。これは、「これ」、または一般に、ヒープ割り当てオブジェクトを受け入れるために機能します。
  • 渡されるオブジェクトへのポインターを共有します(所有しないでください)。この場合、関数の最後でオブジェクトを削除したくないため、scoped_ptr をまったく使用したくありませんこの場合、理論的に必要なのは shared_ptr です (他の場所で linked_ptr と呼ばれているのを見たことがあります)。boost ライブラリにはshared_ptr のバージョンがあり、これは Scott Meyers の効果的な C++ の本 (第 3 版の項目 18) でも推奨されています。

編集:おっと、質問を少し読み違えましたが、この回答が質問に正確に対応していないことがわかりました。これが同様のコードに取り組んでいる人にとって役立つかもしれない場合に備えて、とにかくそのままにしておきます。

于 2008-09-27T00:26:03.887 に答える