127

現在、スマートポインターの使用方法を学ぼうとしています。ただし、いくつかの実験を行っているときに、満足のいく解決策を見つけることができなかった次の状況を発見しました。

クラス A のオブジェクトがクラス B (子) のオブジェクトの親であるとしますが、両者はお互いを認識している必要があります。

class A;
class B;

class A
{
public:
    void addChild(std::shared_ptr<B> child)
    {
        children->push_back(child);

        // How to do pass the pointer correctly?
        // child->setParent(this);  // wrong
        //                  ^^^^
    }

private:        
    std::list<std::shared_ptr<B>> children;
};

class B
{
public:
    setParent(std::shared_ptr<A> parent)
    {
        this->parent = parent;
    };

private:
    std::shared_ptr<A> parent;
};

std::shared_ptr問題は、クラス A のオブジェクトがそれ自体 ( this) をその子にどのように渡すことができるかということです。

Boost 共有ポインター ( for の取得boost::shared_ptrthisstd::) の解決策はありますが、スマート ポインターを使用してこれを処理するにはどうすればよいでしょうか?

4

2 に答える 2

202

std::enable_shared_from_thisこの目的のためだけにあります。.shared_from_this()それを継承し、クラス内から呼び出すことができます。また、ここで循環依存関係を作成しているため、リソース リークが発生する可能性があります。を使用することで解決できますstd::weak_ptr。したがって、コードは次のようになります (子は親の存在に依存し、その逆ではないと仮定します):

class A;
class B;

class A
    : public std::enable_shared_from_this<A>
{
public:
    void addChild(std::shared_ptr<B> child)
    {
        children.push_back(child);

        // like this
        child->setParent(shared_from_this());  // ok
        //               ^^^^^^^^^^^^^^^^^^
    }

private:     
    // note weak_ptr   
    std::list<std::weak_ptr<B>> children;
    //             ^^^^^^^^
};

class B
{
public:
    void setParent(std::shared_ptr<A> parent)
    {
        this->parent = parent;
    }

private:
    std::shared_ptr<A> parent;
};

ただし、呼び出しには、呼び出し時にが所有している.shared_from_this()必要があることに注意してください。つまり、そのようなオブジェクトをスタック上に作成することはできなくなり、通常、コンストラクターまたはデストラクター内から呼び出すことはできません。thisstd::shared_ptr.shared_from_this()

于 2012-07-29T16:54:43.957 に答える
12

あなたの設計にはいくつかの問題がありますが、それはスマート ポインターの誤解に起因しているようです。

スマート ポインターは、所有権を宣言するために使用されます。両方の親がすべての子を所有しているだけでなく、各子がその親を所有していると宣言することで、これを破っています。どちらも真実ではありません。

また、で弱いポインターを返していますgetChild()。そうすることで、呼び出し元が所有権を気にする必要がないことを宣言しています。これは非常に制限される可能性がありますが、そうすることで、問題の子が弱いポインターがまだ保持されている間に破棄されないようにする必要があります。スマートポインターを使用する場合は、それ自体でソートされます。 .

そして最後に。通常、新しいエンティティを受け入れるときは、生のポインターを受け入れる必要があります。スマート ポインターには、親の間で子を交換するための独自の意味がありますが、一般的な使用法では、生のポインターを受け入れる必要があります。

于 2012-07-29T16:57:38.480 に答える