Search code examples
c++algorithmboosttreeptr-vector

boost ptr_vector iterator


I am iterating through the children of a tree node. The children are stored in a ptr_vector, and at some point throughout the iteration I fall into infinite recursion, but I cannot figure out why.

Here is the method where the infinite recursion occurs (this method is just used to print the tree structure into cout):

std::ostream& operator<<(std::ostream &strm, const node &n) {
    if (n.children_.empty())
        return strm << "[]";

    for (boost::ptr_vector<node::edge>::const_iterator iter = n.children_.begin(); iter != n.children_.end(); ++iter)
    {
        if (iter != n.children_.begin())
            strm << ", ";
        strm << "-" << iter->distance << "->[ " << *(iter->dest) << "]";
    }

    return strm;
}

And here is the tree structure I am navigating (note that the purpose of the nested edge is to represent distance between parent and child nodes):

class node
{
public:
    node(void);
    ~node(void);

    node* add_child(unsigned int d);
    node* get_closest(void);

    friend std::ostream& operator<<(std::ostream&, const node&);

private:
    class edge
    {
    public:
        edge(node* n, unsigned int d);
        ~edge(void);

        unsigned int distance;
        node* dest;
    };

    boost::ptr_vector<edge> children_;
};

Additionally, I noticed that this infinite recursion occurs only after the following method has been called:

node* node::get_closest(void) const
{
    if (children_.empty())
        return NULL;

    boost::ptr_vector<node::edge>::const_iterator iter = children_.begin();
    node::edge closest = *iter;
    ++iter;

    if (iter != children_.end())
    {
        for (; iter != children_.end(); ++iter)
        {
            if (iter->distance < closest.distance)
                closest = *iter;
        }
    }

    return closest.dest;
}

Why does this method cause infinite recursion? Thanks!


Solution

  • Going with @RobI's suggestion, there mixture of raw and shared pointers is causing the problem. I changed node::edge closest = *iter; to const node::edge* closest = &(*iter);. Here is the new (and working) version of the method:

    node* node::get_closest(void) const
    {
        if (children_.empty())
            return NULL;
    
        boost::ptr_vector<node::edge>::const_iterator iter = children_.begin();
        const node::edge* closest = &(*iter);
        ++iter;
    
        if (iter != children_.end())
        {
            for (; iter != children_.end(); ++iter)
            {
                if (iter->distance < closest->distance)
                    closest = &(*iter);
            }
        }
    
        return closest->dest;
    }