2010-12-10 24 views
4

boost :: shared_ptrは本当に気になります。確かに、私はこのようなことの有用性を理解していますが、私はshared_ptr<A>A*と使用したいと考えています。 HelpfulContainerは、オブジェクトへのポインタを保持したい他の人のことを考えていなかった作成誰以下のコードC++:オブジェクトへの共有ポインタではなく、共有オブジェクトを作成する

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. 
} 

を考えてみましょう。 HelpfulClassにboost :: shared_ptrオブジェクトを与えることはできません。しかし、我々は何ができる一つのことは、Aである自分自身SharedAを作成するためにpimlpイディオムを使用している:

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; 
}; 

そして主な機能は次のようなものに見えることができます:私、そう

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にはまだデータ構造が必要です。


更新:このquestionは、後に続く質問です。

+0

HelpfulContainerがポインタの所有権を取得したい場合は、正しいセマンティクスを使用する必要があります。インターフェース 'eventHorizo​​n'は、何が起こっているのかを説明していないので、所有名が転送されていることを示すパラメータ(例えば、std :: auto_ptrまたはその新しい置換std :: unique_ptr)が記述されています。これらの両方は、HelpfullContainerオブジェクトがオブジェクトの所有権を取得しているため、呼び出し後も有効ではなくなることを示します。したがって、C++コードでは、言語の意味を理解していない人がひどく書くことができるという点を証明します。 –

答えて

6

shared_ptrの全体のポイントがあること、それ(とそのコピー)が指すオブジェクトを所有しています。寿命を管理するコンテナにAを指定する場合は、必要に応じてshared_ptrを使用しないでください。 HelpfulContainerは、動的に作成されるオブジェクトの唯一の所有者であることを知っているだけなので、他のものが所有していないオブジェクトへのポインタを与える必要があります。

通常はということは、自分の生涯を気にするオブジェクト(例外があります)のデザインが悪いと思います。通常、オブジェクトがジョブを実行し、他の何かがその作成と記述を管理し、最も簡単なライフタイム戦略(例えば、ローカル/自動変数)を選択する場合には、より便利です。

協力していない2つのもの(例えばshared_ptrHelpfulContainerなど)間で所有権を共有する必要がある場合は、何らかのプロキシ技術を使用する必要があります。

この場合、HelpfulContainerのように見えますが、あなたの状況にはあまり役立ちません。

+1

+1:ちょうどその気が重いコンテナを変更して(そしてそれを使ってコードを慎重に見直してください)、例えばshared_ptrを使って過負荷を追加すると便利です。 –

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)); 
} 
1

これはあなたのために何をするのか分かりません。

helpfulContainer.eventHorizon()常には、なぜちょうど(オリジナル)クラスの新しいコピーを渡すことはなく、そのパラメータを削除した場合:helpfulContainer.eventHorizon()だけ時々そして作り、そのパラメータを削除した場合

helpfulContainer.eventHorizon(new A(sa1)); 

か、を

helpfulContainer.eventHorizon(new SharedA(sa1)); 

として呼び出しが SharedA、元A(S 両方が漏れますa1)削除しないことを選択した場合。

+0

eventHorizo​​nがポインタを削除しないが、そのポインタをデータ構造のどこかに格納するケース。関連するshared_ptrsがすべて削除された場合、データ構造に隠れている無効なポインタが存在します。 – JnBrymn

+0

eventHorizo​​nがポインタの所有権を得て、それを最終的に削除し、あなた自身の所有権を保持する必要があることを知っていれば、私が示した最初の形式のように新しいコピーを渡します( 'helpfulContainer.eventHorizo​​n (新しいA(sa1));)。 –

+0

@John Berryman:たぶん私はあなたのコメントを誤解しました。あなたの最初の文章に:eventHorizo​​nがポインタを保持し、それを余裕で削除しても、同じオブジェクトにアクセスする必要がある場合は、あなたの提案**が役立つかもしれません。しかし、あなたのコードを非常に徹底的にリファクタリングして、未加工の 'A'オブジェクトへのポインタが' SharedA'オブジェクト以外で使われることはないようにする必要があります。両者を混ぜようとすると、泣き叫び、歯が痛む。私は 'mImpl'をコピーするSharedA(const SharedA&)のための特殊なコピーコンストラクタが必要だと思います。 –

0

shared_ptrを実現することなく、非常に簡単に関数などに渡すことができるという意味で、基になるポインタ型への暗黙的な変換は、shared_ptrの意図された使用と矛盾します。

HelpfulContainerは役に立ちましたが、固定したり、捨てたりする必要があります。

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

関連する問題