
https://svn.lrde.epita.fr/svn/oln/trunk/milena I need to check whether we could get rid of all those dynamic allocations. I think so, but I'm unsure. Index: ChangeLog from Roland Levillain <roland@lrde.epita.fr> Address memory leaks in graphs. * mln/util/internal/graph_base.hh (mln::util::internal::graph_base<N, E>::self_t): New typedef. (mln::util::internal::graph_base<N, E>::nodes_t) (mln::util::internal::graph_base<N, E>::edges_t) (mln::util::internal::graph_base<N, E>::edges_set_t): Help the compiler find types util::node and util::egde. (mln::util::internal::graph_base<N, E>::graph_base(const self_t&)): New copy ctor. (mln::util::internal::graph_base<N, E>::operator=(const self_t&)): New assignment operator. (mln::util::internal::graph_base<N, E>::~graph_base): Remove dynamically allocated data. graph_base.hh | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 69 insertions(+), 11 deletions(-) Index: mln/util/internal/graph_base.hh --- mln/util/internal/graph_base.hh (revision 1881) +++ mln/util/internal/graph_base.hh (working copy) @@ -151,22 +151,26 @@ template<typename N, typename E> class graph_base { + typedef graph_base<N, E> self_t; + public: /* FIXME: Do we really want handle nodes and edges through pointers? In my (Roland) opinion, this is just a drawback, here. */ /// The type of the set of nodes. - typedef std::vector< node<N>* > nodes_t; + typedef std::vector< util::node<N>* > nodes_t; /// The type of the set of edges. - typedef std::vector< edge<E>* > edges_t; + typedef std::vector< util::edge<E>* > edges_t; /// A set to test the presence of a given edge. - typedef std::set< edge<E>* > edges_set_t; - + typedef std::set< util::edge<E>* > edges_set_t; - /// Constructor. + /// Construction, assignments and destruction. + /// \{ graph_base(); - /// Destructor. + graph_base(const self_t& rhs); + self_t& operator=(const self_t& rhs); ~graph_base(); + /// \} /// Return the node whose id is \a n. /// \{ @@ -243,9 +247,9 @@ namespace internal { - /*----------------. - | Ctor and dtor. | - `----------------*/ + /*--------------------------------------------. + | Construction, assignments and destruction. | + `--------------------------------------------*/ template<typename N, typename E> inline @@ -256,10 +260,64 @@ template<typename N, typename E> inline + graph_base<N, E>::graph_base(const graph_base<N, E>& rhs) + : nodes_(), edges_(), edges_set_() + { + nodes_.reserve(rhs.nodes_.size()); + edges_.reserve(rhs.edges_.size()); + for (typename nodes_t::const_iterator n = rhs.nodes_.begin(); + n != rhs.nodes_.end(); ++n) + nodes_.push_back(new util::node<N>(**n)); + for (typename edges_t::const_iterator e = rhs.edges_.begin(); + e != rhs.edges_.end(); ++e) + edges_.push_back(new util::edge<E>(**e)); + std::copy(edges_.begin(), edges_.end(), + std::insert_iterator<edges_set_t>(edges_set_, + edges_set_.begin())); + } + + template<typename N, typename E> + inline + graph_base<N, E>& + graph_base<N, E>::operator=(const graph_base<N, E>& rhs) + { + if (this != &rhs) + { + /// Free previous nodes and edges. + for (typename nodes_t::iterator n = nodes_.begin(); + n != nodes_.end(); ++n) + delete *n; + for (typename edges_t::iterator e = edges_.begin(); + e != edges_.end(); ++e) + delete *e; + edges_set_.clear(); + /// Assign values from RHS. + nodes_.reserve(rhs.nodes_.size()); + edges_.reserve(rhs.edges_.size()); + for (typename nodes_t::const_iterator n = rhs.nodes_.begin(); + n != rhs.nodes_.end(); ++n) + nodes_.push_back(new util::node<N>(**n)); + for (typename edges_t::const_iterator e = rhs.edges_.begin(); + e != rhs.edges_.end(); ++e) + edges_.push_back(new util::edge<E>(**e)); + std::copy(edges_.begin(), edges_.end(), + std::insert_iterator<edges_set_t>(edges_set_, + edges_set_.begin())); + } + return *this; + } + + template<typename N, typename E> + inline graph_base<N, E>::~graph_base() { - // FIXME: Delete data dynamically allocated in nodes_ and - // edges_. + for (typename nodes_t::iterator n = nodes_.begin(); n != nodes_.end(); + ++n) + delete *n; + for (typename edges_t::iterator e = edges_.begin(); e != edges_.end(); + ++e) + delete *e; + edges_set_.clear(); } /*------------.