質問

走って向かいました enable_shared_from_this Boost.Asio の例を読んでいる間、そしてドキュメントを読んだ後でも、これをどのように正しく使用するべきか迷っています。誰かがこのクラスを使用するのが理にかなっている場合の例や説明を教えてください。

他のヒント

ます。http:// drdobbs

弱いポインタの博士ドブスの記事から、私はこの例では、(ソースを理解することが容易だと思います.COM / CPP / 184402026 に):

...このようなコードが正しく動作しません。

int *ip = new int;
shared_ptr<int> sp1(ip);
shared_ptr<int> sp2(ip);

2つのshared_ptrオブジェクトのどちらも他を知っているので、両方のは、それらが破壊されたときにリソースを解放しようとします。これは通常、問題につながります。

メンバ関数は、それが呼び出されていているオブジェクトを所有しているshared_ptrオブジェクトを必要とする場合は、

同様に、それだけでその場でオブジェクトを作成することはできません。

struct S
{
  shared_ptr<S> dangerous()
  {
     return shared_ptr<S>(this);   // don't do this!
  }
};

int main()
{
   shared_ptr<S> sp1(new S);
   shared_ptr<S> sp2 = sp1->dangerous();
   return 0;
}
より微妙な形態であるが、

このコードは、前の例と同様の問題があります。それが構築されると、shared_ptrオブジェクトsp1は、新たに割り当てられたリソースを所有しています。メンバ関数S::dangerous内のコードは、そのshared_ptrオブジェクトについて知らないので、それは戻りshared_ptrオブジェクトはsp1区別されます。 shared_ptrに新しいsp2オブジェクトをコピーする助けにはなりません。 sp2がスコープの外に出たとき、それがリソースを解放し、sp1がスコープの外に出るときは、再度リソースを解放します。

この問題を回避する方法は、クラステンプレートenable_shared_from_thisを使用することです。テンプレートは、管理対象リソースを定義するクラスの名前である1つのテンプレート型引数を取ります。そのクラスは、今度は、テンプレートから公に導き出されなければなりません。このような:

struct S : enable_shared_from_this<S>
{
  shared_ptr<S> not_dangerous()
  {
    return shared_from_this();
  }
};

int main()
{
   shared_ptr<S> sp1(new S);
   shared_ptr<S> sp2 = sp1->not_dangerous();
   return 0;
}

あなたがこれを行うと、あなたはshared_from_this呼び出しているオブジェクトがshared_ptrオブジェクトによって所有されなければならないことに注意してください。これは動作しません。

int main()
{
   S *p = new S;
   shared_ptr<S> sp2 = p->not_dangerous();     // don't do this
}

これが基本的な観点からの私の説明です(一番上の回答は私にはピンと来ませんでした)。※これはVisual Studio 2012に付属するshared_ptrとenable_shared_from_thisのソースを調査した結果であることに注意してください。おそらく他のコンパイラは、enable_shared_from_this を別の方法で実装している可能性があります...*

enable_shared_from_this<T> プライベートを追加します weak_ptr<T> インスタンスへ T 'を保持する1 つの真の参照カウント' の例としては T.

したがって、最初に作成するときは、 shared_ptr<T> 新しい T* に追加すると、その T* の内部weak_ptr が refcount 1 で初期化されます。新しい shared_ptr 基本的にこれに戻ります weak_ptr.

T その後、そのメソッド内で以下を呼び出すことができます shared_from_this のインスタンスを取得するには shared_ptr<T> それ 内部的に保存されている同じ参照カウントに戻ります. 。こうすることで、常に 1 つの場所が確保されます。 T*の ref-count は複数を持つのではなく保存されます。 shared_ptr インスタンスはお互いのことを知らず、それぞれが自分たちを自分だと思っています。 shared_ptr それは参照カウントを担当します T そして、ref-count がゼロに達したときにそれを削除します。

ブーストを使用していることに注意してください:: intrusive_ptrがこの問題に悩まされません。 これは、多くの場合、この問題を回避するために、より便利な方法です。

これは、C ++ 11以降ではまったく同じだ:それはthisはあなたに生のポインタを与えますので、共有ポインタとしてthis戻す機能を有効にすることです。

他の言葉で、それはあなたがこのようなコードをオンにすることができます。

class Node {
public:
    Node* getParent const() {
        if (m_parent) {
            return m_parent;
        } else {
            return this;
        }
    }

private:

    Node * m_parent = nullptr;
};           

このへ

class Node : std::enable_shared_from_this<Node> {
public:
    std::shared_ptr<Node> getParent const() {
        std::shared_ptr<Node> parent = m_parent.lock();
        if (parent) {
            return parent;
        } else {
            return shared_from_this();
        }
    }

private:

    std::weak_ptr<Node> m_parent;
};           

もう一つの方法は、weak_ptr<Y> m_stubclass Yメンバーを追加することです。その後、書き込みます:

shared_ptr<Y> Y::f()
{
    return m_stub.lock();
}

便利なあなたが(例えば、他の人のライブラリを拡張する)から派生しているクラスを変更することができないとき。例えば、メンバーを初期化することを忘れないでくださいm_stub = shared_ptr<Y>(this)によって、そのでも、コンストラクタ時に有効です。

このような多くのスタブが継承階層に存在する場合、それはオブジェクトの破壊を防ぐことはできませんOKです。

編集のように正しくユーザーnobarが指摘割り当てが終了すると、一時的な変数が破壊された場合、コードはYオブジェクトを破壊するであろう。したがって、私の答えは間違っています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top