3

と の 2 つのクラスがあるThingとしHolderます。

struct Thing :
        std::enable_shared_from_this<Thing>
{
    std::shared_ptr<Thing> self()
    {
        return shared_from_this();
    }
};

struct Holder :
        std::enable_shared_from_this<Holder>
{
    Thing t;
};

int main()
{
    auto h = std::make_shared<Holder>();
    // will throw std::bad_weak_ptr
    h->t.self();
}

toを保持する必要があるのではなく、Thing内部weak_ptrで共有カウントを使用したいと思います。反対に、a が何であるかを知らなくても存在できる必要があります(まだ機能するはずです)。私が探しているものを達成するためのまともな方法はありますか?Holder Holdershared_ptrThingThingHolderstd::make_shared<Thing>().self()


うまくいかないこと

std::shared_ptr<Thing> t(h, &h->t);a のエイリアシング コンストラクターはビジターstd::shared_ptrを使用しないため、ようなことを言っても機能しません。enable_shared_from_this

ブーストを使用すると、オーバーロードすることでこれを回避できsp_enable_shared_from_thisます。ただし、g++ の実装では、同等のことを行う方法が明らかではありません__enable_shared_from_this_helper(言うまでもなく、"DON'T DO THAT" ランドに飛び込んでいます)。


ブーストの回避策

_internal_accept_ownerBoost の場合、直接呼び出してこの問題を回避することはそれほど難しくありません。

int main()
{
    auto h = boost::make_shared<Holder>();
    h->t._internal_accept_owner(&h, &h->t);
    h->t.self();
}

を使用すると、次のようなboost::enable_shared_from_this2コンストラクターに必要なコードを埋め込むことができます。Holder

Holder()
{
    boost::shared_ptr<Holder> self = shared_from_this();
    t._internal_accept_owner(&self, &t);
}

と同等のことをしようとしていstd::enable_shared_from_thisます。

4

2 に答える 2

2

わかりました、あなたが求めていることを理解したので、ここに別の方法があります。shared_ptr< Holder >toを渡すことで、Thing独自のエイリアス化された shared_ptr を作成できます。このようなもの:

struct Thing : std::enable_shared_from_this<Holder>
{
     Thing() {};

     Thing( std::shared_ptr< Holder >& holderPtr ) :
     m_holder( holderPtr )
     {
     }

     std::shared_ptr< Holder > m_holder;


     std::shared_ptr<Thing> self()
     {
         try 
         { 
              return shared_from_this(); 
         }
         catch( const std::bad_weak_ptr& )
         {
              return std::shared_ptr< Thing >( m_holder, this );    
         }
     }
};

struct Holder : std::enable_shared_from_this<Holder>
{
    Thing t;
};

shared_ptr< Thing >個人的にはinsideだけ持った方が良さHolderそうですが、好みならこれでも良さそうです。Holderとの間の循環参照は別としてThing。代わりにweak_ptr< Holder >内部を使用できると思います。Thing

于 2012-11-27T18:44:57.900 に答える
1

気にしない場合は、メンバー オブジェクトではなく、プライベート継承を介してThing内部の構成をモデル化できます。Holder次に、あなたのメンバー内で、ダウンキャストThingで囲んでいるものを「取得」できます。その後、共有カウントへのアクセスを取得するために使用します。Holderstatic_cast<Holder&>(*this)shared_from_this

ただし、 のプライベート ベースであるためHolderThingダウンキャストを実行するには、フレンド宣言が必要です。それに加えて、2 つのクラス間の依存関係は循環的であるため、ある程度の結合が強くなります。

于 2012-11-27T19:47:41.500 に答える