Currently, I manually manage the life cycle of objects in my project. I am considering switching to smart pointers, in particular tr1 :: shared_pointer and tr1 :: weak_ptr. Nevertheless, I see a couple of problems and would like to get some input into best practices.
Consider the following class diagram:
In this diagram, thick arrows represent associations with property semantics (the source is responsible for deleting the target or goals). Thin arrows represent associations without ownership.
From what I understand, one way to implement associations with property semantics would be to use tr1 :: shared_ptr (or a collection of them). Other associations can be implemented using either tr1 :: shared_ptr or tr1 :: weak_ptr. The first is prohibited if this can lead to circular references, as this will prevent proper allocation of resources.
As you can see, there is a circle of associations between the Edge and Side classes. I can easily break this by implementing the "left" and "right" associations from Edge to Side using tr1 :: weak_ptrs. However, I would prefer to use smart pointers to document the semantics of property associations. Therefore, I would like to use shared_ptrs only for associations represented by thick arrows in the diagram, and weak_ptrs for everything else.
Now my first question is: should weak_ptrs be used liberally, as described above, or should I use them as little as possible (just to avoid circular references)?
The next question: suppose I have a function that calculates the average value of a set of vertices. Suppose further that I implemented the association from the polyhedron to its vertices as follows:
class Vertex; class Polyhedron { protected: std::vector<std::tr1::shared_ptr<Vertex> > m_vertices; };
and that I implemented an association from side to its tops, for example:
class Vertex; class Side { protected: std::vector<std::tr1::weak_ptr<Vertex> > m_vertices; };
Note that the set of Side vertices is a subset of the set of vertices of a polyhedron. Now suppose I have a function that calculates the average of a set of vertices. Currently, the function is declared like this:
const Vertex centerOfVertices(std::vector<Vertex*> vertices);
Now, if I represent associations, as indicated above, I suddenly need two functions, if I understand everything correctly:
const Vertex centerOfVertices(std::vector<std::tr1::shared_ptr<Vertex> > vertices); const Vertex centerOfVertices(std::vector<std::tr1::weak_ptr<Vertex> > vertices);
Because I cannot convert the shared_ptr vector and weak_ptr vector. This is funny for me. I would like to know what approach I should take here to avoid this situation.