現在、プロジェクト内のオブジェクトのライフサイクルを手動で管理しています。スマートポインタ、具体的には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のベクトルの間で変換できないためです。これは私には面白いにおいがします。このような状況を回避するために、ここでどのようなアプローチを取るべきかを知りたいと思います。