2016-12-17 5 views
3

私はC++でポインタの問題を解決しようとするといくつかの困難を抱えています。共有ポインターで一意のポインターを指すようにしても構いませんか?

私はMyClassと呼ばれるクラスを持っているとしましょう。このクラスの内部には、MyResourceという外部リソースを指す共有ポインタがあります。 MyClassの中に、MyObjectというオブジェクトのインスタンスがいくつかあるとしましょう。 MyObjectの各インスタンスもMyResourceを参照する必要があります。のは、このクラスは、私はちょうど私が以前に(しようとした)していた方法

class MyClass 
{ 
    shared_ptr<MyResource> m_p_my_resource; 
    MyObject m_my_object1; 
    MyObject m_my_object2; 
    MyObject m_my_object3; 
} 

を述べてきたこれらのコンポーネントが含まれている以外何もしないと仮定しましょう、私は共有のポインタを作成し、m_p_my_resourceにそれを与えるだろう、これを実装しました。私はMyObjectの各インスタンスにm_p_my_resourceを与えます。 m_p_my_resourceが新しいMyResourceを指すように変更されたときはいつでも、MyObjectのそれぞれが新しいリソースを指していると思いました。

しかし、私が行ったことは正しいとは思いません。 m_p_my_resourceを変更すると、これは実際には新しいリソースを指しているはずです。しかし、MyObjectの各インスタンスは、依然として元のMyResourceを指しています。

今私が元々しようとしていたことを実際に実装する方法について考えてみよう:m_p_my_resourceを変更できるようにし、各インスタンスも新しいリソースを指すようにする。

これを解決する1つの方法は、m_p_my_resourceが変更されるたびにMyObjectの各インスタンスを更新することです。私はおそらくメソッドを持って、m_p_my_resourceを更新してからMyObjectの各インスタンスを反復処理する必要があります。

代わりの解決方法は、の各インスタンスにポインタMyResourceのポインタを含めることです。したがって、各MyObjectがリソース自体の代わりにリソースへのポインタを指していた場合、私はm_p_my_resourceを変更することができ、各オブジェクトは新しいリソースを決定することもできます。

この2番目の方法はおそらく上記のクラスの例では機能しますが、クラス内に含まれていないMyObjectのインスタンスに対してはエレガントではありません。私が単純にスタックにMyObjectを作成した場合、リソースを指している中間のポインタを指すのではなく、直接リソースを指すようにします。

私が記述したものを実装するための最良の方法を決定する。私はスマートなポインタにはまだ比較的新しいですし、私がやろうとしていることがばかばかしい場合、あるいはより良い/明白な代替ソリューションがあれば、興味があります。

+1

最初のソリューションは、それを行うための適切なオブジェクト指向の方法です。適切なカプセル化を保証し、(MyResourceが不変であると仮定して)すべてのデータ構造を非偶発的に保ちます。 – sbabbi

答えて

3

それはMyObject秒の寿命がMyClassの寿命と同じであることは事実であるならば、MyObjectの各インスタンスではなく、あなたが望むものを達成するためにshared_ptr<...>への参照またはポインタを保持することができます。

class MyClass { 
public: 
    shared_ptr<MyResource> resource; 
    MyObject obj1 { resource }; 
    MyObject obj2 { resource }; 
}; 

class MyObject { 
public: 
    shared_ptr<MyResource>& resource; 
    void foo() { 
     resource->do_something(); // works transparently 
    } 
} 

そして、あなたは安全にMyClass::resourceの内容を変更することができます

void bar(MyClass& myClass) { 
    myClass.resource.reset(new MyResource()); 
    assert(myClass.resource.get() == myClass.ob1.resource.get()); 
    assert(myClass.resource.get() == myClass.ob1.resource.get()); 
} 
+0

あなたは生涯を正しく仮定しました。これは最も洗練されたソリューションのようです。私はヒープ割り当て/未知の生涯オブジェクトのために意図されているという事実を考慮せずに、いつでもスマートポインタを常に使用するという犠牲者に陥ったと思います。 – Izzo

2

ダブルポインタは、問題を解決するための正確な手法です。

しかし、私はちょっとあなたがあなたのタイトルで言うようにunique_ptrshared_ptrにしたいと思っています。質問の本文にはどこにでもunique_ptrが記載されておらず、実際に欲しいものはshared_ptr<unique_ptr<MyResource>>で、unique_ptr<shared_ptr<MyResource>>ではありません。

+0

タイトルを残念に思うのは、タイトルを書いて、タイトルを編集するのを忘れて解決しようとしていた実際の問題をタイプする古典的なケースでした。あなたの答えに戻って、 'MyObject'がクラスに含まれていないとき、あなたは厄介なことを説明していませんか?他のシナリオでは、 'MyObject'に直接リソースへの参照が含まれている方が理にかなっています。思考? – Izzo

+0

これは通常、理想的です。しかし、すべてのインスタンスがどのオブジェクトを指しているのかを同時に変更する機能と、ダブルポインタが必要なことを尋ねました。しかし、ポインタは実際には共有されたりユニークである必要はありません。通常のポインタを使うことができますが、メモリを自分で管理する必要があります。 – IanPudney

関連する問題