4

現在、プロジェクト内のオブジェクトのライフサイクルを手動で管理しています。スマートポインタ、具体的にはtr1::shared_pointerとtr1::weak_ptrへの切り替えを検討しています。ただし、いくつかの問題が発生しているため、ベストプラクティスに関する情報を入手したいと思います。

次のクラス図を検討してください。

多面体クラス図

この図では、太い矢印は所有権セマンティクスとの関連付けを表しています(ソースは1つまたは複数のターゲットを削除する責任があります)。細い矢印は、所有権のない関連付けを表しています。

私が理解していることから、所有権セマンティクスとの関連付けを実装する1つの方法は、tr1 :: shared_ptr(またはそのコレクション)を使用することです。他の関連付けは、tr1::shared_ptrまたはtr1::weak_ptrのいずれかを使用して実装できます。前者は、リソースの適切な解放を妨げるため、循環参照になる可能性がある場合は禁止されています。

ご覧のとおり、EdgeクラスとSideクラスの間には関連付けの輪があります。tr1 :: weak_ptrsを使用して、エッジからサイドへの「左」と「右」の関連付けを実装することで、これを簡単に破ることができます。ただし、スマートポインターを使用して、関連付けの所有権のセマンティクスをコードで文書化することをお勧めします。そのため、図の太い矢印で表されている関連付けにはshared_ptrsのみを使用し、それ以外にはweak_ptrsを使用します。

ここで、最初の質問は次のとおりです。weak_ptrsを上記のように自由に使用する必要がありますか、それとも(循環参照を避けるために)できるだけ使用しないでください。

次の質問は次のとおりです。頂点のセットの平均を計算する関数があるとします。さらに、次のように多面体からその頂点への関連付けを実装したとします。

class Vertex;
class Polyhedron {
protected:
    std::vector<std::tr1::shared_ptr<Vertex> > m_vertices;
};

そして、私はサイドからその頂点への関連付けを次のように実装しました。

class Vertex;
class Side {
protected:
    std::vector<std::tr1::weak_ptr<Vertex> > m_vertices;
};

サイドの頂点のセットは、多面体の頂点のセットのサブセットであることに注意してください。ここで、頂点のセットの平均を計算する関数があるとしましょう。関数は現在、次のように宣言されています。

const Vertex centerOfVertices(std::vector<Vertex*> vertices);

上記のように関連付けを表す場合、すべてを正しく理解していれば、突然2つの関数が必要になります。

const Vertex centerOfVertices(std::vector<std::tr1::shared_ptr<Vertex> > vertices);
const Vertex centerOfVertices(std::vector<std::tr1::weak_ptr<Vertex> > vertices);

shared_ptrのベクトルとweak_ptrのベクトルの間で変換できないためです。これは私には面白いにおいがします。このような状況を回避するために、ここでどのようなアプローチを取るべきかを知りたいと思います。

4

3 に答える 3

1

ただし、スマートポインターを使用して、関連付けの所有権のセマンティクスをコードで文書化することをお勧めします。

あなたがすべきように。結局のところ、それが彼らが完璧に表現していることです。

そのため、図の太い矢印で表されている関連付けにはshared_ptrsのみを使用し、それ以外にはweak_ptrsを使用します。

注意点が1つあります。所有権は共有所有権のようには見えません。単純で、一意の所有権です。したがって、ここでの適切なスマートポインターはshared_ptr、ではなくstd::unique_ptr、であり、弱いポインターは単に生のポインターになります。

上記のように関連付けを表すと、突然2つの関数が必要になります…</ p>

はい。または、テンプレートを使用します。

あるいは、関数は実際には所有権の共有にまったく関心がないため、生のポインターを関数に渡すことができますが、これはもちろん、最初に構造から生のポインターを取得することを意味します。これには、クライアントに追加の手順が必要ですが、そうでない場合もあります。インターフェースに適しています。

于 2012-06-13T13:55:15.303 に答える
1

共有ポインタを使用することは賢明なようです。特に、頂点などを多面体間で共有できる場合があります。

弱いポインターのベクトルから共有ポインターのベクトルに変換するには、明示的なコンストラクターを使用します。

centerOfVertices(std::vector<std::tr1::shared_ptr<Vertex> >(vertices.begin(), vertices.end()));
于 2012-06-13T16:02:08.533 に答える
0

循環参照には、shared_ptrを使用することもできます。これが実際に理にかなっているいくつかのまれな状況があります。ただし、オブジェクトの処理が完了したら、サイクルを中断するように注意する必要があります。

于 2012-06-13T14:04:15.983 に答える