4

boost::shared_ptrは本当に気になります。確かに、そのようなものの有用性は理解していますが、shared_ptr<A> として使用できればと思いA*ます。次のコードを検討してください

class A
{
public:
    A() {}
    A(int x) {mX = x;}
    virtual void setX(int x) {mX = x;}
    virtual int getX() const {return mX;}
private:
    int mX;
};


class HelpfulContainer
{
public:
    //Don't worry, I'll manager the memory from here.
    void eventHorizon(A*& a)
    {
        cout << "It's too late to save it now!" << endl;
        delete a;
        a = NULL;
    }
};


int main()
{
    HelpfulContainer helpfulContainer;

    A* a1 = new A(1);
    A* a2 = new A(*a1);
    cout << "*a1 = " << *a1 << endl;
    cout << "*a2 = " << *a2 << endl;
    a2->setX(2);
    cout << "*a1 = " << *a1 << endl;
    cout << "*a2 = " << *a2 << endl;
    cout << "Demonstrated here a2 is not connected to a1." << endl;

    //hey, I wonder what this event horizon function is.
    helpfulContainer.eventHorizon(a1);

    cout << "*a1 = " << *a1 << endl;//Bad things happen when running this line.
}

HelpfulContainerを作成した人は誰でも、Aオブジェクトへのポインターを保持したい他の人について考えていませんでした。HelpfulClass boost::shared_ptrオブジェクトを提供することはできません。しかし、私たちができることの1つは、pimlpイディオムを使用して、それ自体がAであるSharedAを作成することです。

class SharedA : public A
{
public:
    SharedA(A* a) : mImpl(a){}
    virtual void setX(int x) {mImpl->setX(x);}
    virtual int getX() const {return mImpl->getX();}
private:
    boost::shared_ptr<A> mImpl;
};

そして、main関数は次のようになります。

int main()
{
    HelpfulContainer helpfulContainer;

    A* sa1 = new SharedA(new A(1));
    A* sa2 = new SharedA(sa1);
    cout << "*sa1 = " << *sa1 << endl;
    cout << "*sa2 = " << *sa2 << endl;
    sa2->setX(2);
    cout << "*sa1 = " << *sa1 << endl;
    cout << "*sa2 = " << *sa2 << endl;
    cout << "this demonstrates that sa2 is a shared version of sa1" << endl;

    helpfulContainer.eventHorizon(sa1);
    sa2->setX(3);
    //cout << "*sa1 = " << *sa1 << endl;//Bad things would happen here
    cout << "*sa2 = " << *sa2 << endl; 
    //but this line indicates that the originally created A is still safe and intact.
    //only when we call sa2 goes out of scope will the A be deleted.
}

だから、私の質問はこれです:上記のパターンは良いパターンですか、それとも私がまだ検討していないものがありますか?私の現在のプロジェクトは、HelpfulContainer必要なポインターを削除する上記のようなクラスを継承しましたが、HelpfulContainerに存在するデータ構造が必要です。


更新:この質問は後続の質問です。

4

4 に答える 4

6

要点shared_ptrは、それ (およびそのコピー) が、それが指すオブジェクトを所有しているということです。Aライフタイムを管理するコンテナにを渡したい場合はshared_ptr、ニーズを満たさないため、まったく使用しないでください。HelpfulContainer動的に作成されたオブジェクトの唯一の所有者になる方法しか知らないため、他のオブジェクトが所有していないオブジェクトへのポインターを渡す必要があります。

通常、オブジェクトが自身のライフタイムを気にするのは設計が悪いと思います(例外もあります)。通常、オブジェクトがジョブを実行でき、他の何かがその作成と記述を管理し、可能な限り単純なライフタイム戦略 (ローカル/自動変数など) を選択すると、より便利です。

協調しない 2 つのもの ( と など) の間で所有権を絶対に共有するshared_ptr必要HelpfulContainerがある場合は、何らかのプロキシ手法を使用する必要があります。

ただし、この場合、状況にはあまり役に立たないように見えHelpfulContainerます。

于 2010-12-10T17:03:42.147 に答える
1

これがあなたにとって何をするのかわかりません。

helpfulContainer.eventHorizon() 常にそのパラメーターを削除する場合は、(元の) A クラスの新しいコピーを渡すだけではどうですか。

  helpfulContainer.eventHorizon(new A(sa1));

または、そのパラメーターをhelpfulContainer.eventHorizon() 時々削除する場合は、次のように呼び出しを行います

  helpfulContainer.eventHorizon(new SharedA(sa1)); 

削除しないことを選択した場合、SharedA と元の A (sa1) の両方がリークします。

于 2010-12-10T17:09:48.870 に答える
0

基になるポインター型への暗黙的な変換は、関数などに気付かずにshared_ptr非常に簡単に渡すことができるという点で、 の意図された使用法と矛盾しています。shared_ptr

私にHelpfulContainerは役に立たないように思えますが、修正するか破棄する必要があります。

それが不可能な場合、おそらく最善の方法は、A渡したい をコピーして、そのコピーをコンテナーに渡すことです。

于 2010-12-10T18:31:05.853 に答える
0

したがって、削除しても問題ないスタンドイン (SharedA) を作成しています。これはちょっと厄介ですが、レガシー API を使用する必要があると思います。これを少し改善するには: shared_ptr からの SharedA の構築を許可しますが、その逆は許可しません。次に、絶対に必要な場合にのみ SharedP を使用します。

int main()
{
  HelpfulContainer helpfulContainer;

  boost::shared_ptr<A> sa1(new A(1));

  // deletes its parameter, but that's okay
  helpfulContainer.eventHorizon(new SharedA(sa1)); 
}
于 2010-12-10T16:23:40.370 に答える