0

I am trying to store iterators of a deque in a vector and want to preserve them inside the vector even when I have erased or inserted some elements from or into the deque. Is this possible?

I have the following code:

typedef struct {

int id;
int seedId;
double similarity;

} NODE_SEED_SIM;

typedef std::deque<NODE_SEED_SIM> NodesQueue;
typedef std::deque<NODE_SEED_SIM>::iterator ITRTR;
typedef std::vector<const ITRTR> PointerVec;  

void growSegments (CSG_PointCloud *pResult, IntMatrix *WdIndices, NodesQueue *NodesList, IntMatrix *Segments) {

    ITRTR nodeslistStart = (*NodesList).begin();
    int pointCount = (*WdIndices).size();
    int nodeslistSize = (*NodesList).size();

    IntVector book(pointCount);
    PointerVec pointerList (pointCount); // Vector of ITRTRs

    for (int i = 0; i < nodeslistSize; i++) {

         book [ (*NodesList)[i].id ] = 1;
         pointerList [ (*NodesList)[i].id ] = nodeslistStart + i; // REF: 2

    }

    while (nodeslistSize > 0) {

    int i = 0;
    int returnCode = 0;
    int nodeId = (*NodesList)[i].id;
    int seedId = (*NodesList)[i].seedId;
    int n_nbrOfNode = (*WdIndices)[ nodeId ].size();

    (*Segments)[ seedId ].push_back ( nodeId );
    (*NodesList).erase ( (*NodesList).begin() ); // REF: 3; This erase DOES NOT mess the pointerList
    nodeslistSize --;

    Point node;
    /*
               GET ATTRIBUTES OF NODE
            */

    for (int j = 0; j < n_nbrOfNode; j++) {

        int nborId = (*WdIndices)[nodeId][j];

        if (nborId == seedId)
            continue;

        Point neighbor;
        /*
                        GET ATTRIBUTES OF NEIGHBOUR
                    */

        double node_nbor_sim = computeSimilarity (neighbor, node);

        if (book[nborId] == 1) {

            ITRTR curr_node = pointerList[nborId]; // REF: 1

            if ( curr_node -> similarity < node_nbor_sim) {

                curr_node -> similarity = node_nbor_sim;
                NODE_SEED_SIM temp = *curr_node;
                (*NodesList).erase (curr_node); // REF: 4; This erase completely messes up the pointerList
                returnCode = insertSortNodesList (&temp, NodesList, -1);


            }

        }

    }

}

}

The nodes in the NodesList hold a global ID inside them. However they are stored in NodesList, not according to this global ID but in descending order of their "similarity". So later when I want to get the node from NodesList corresponding to a global ID (nborID in code)[REF: 1] I do it via the "pointerList" where I have previously stored the iterators of the deque but according to the global IDs of the nodes [REF: 2]. My pointerList stays true after the first erase command [REF: 3], but gets messed up in the next erase [REF: 4].

What is wrong here? Thanks

Avishek Dutta
  • 97
  • 2
  • 11

2 Answers2

4

I am trying to store iterators of a deque in a vector and want to preserve them inside the vector even when I have erased or inserted some elements from or into the deque. Is this possible?

As from the documentation it says

enter image description here Sorry I'm posting this as an image here, but the formatting is too tedious to replicate in markup!

So the short answer is: NO! I'm afraid you cannot safely store iterators pointing to certain elements stored in a std::deque, while it's changed elsewhere.

Some other relevant Q&A:

Community
  • 1
  • 1
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
-1

If you want to create a vector of iterators then this is what you want to do:

#include<iostream>
#include <deque>
#include <vector>
using namespace std;
int main()
{
    deque<int> dq { 1, 2, 3, 4, 5, 6, 7, 8 };
    deque<int>::iterator it;

    vector<deque<int>::iterator> vit;
    for (it = dq.begin(); it != dq.end(); it++)
    {
        vit.push_back(it);
        cout << *it;
    }

    //note that `it` is a pointer so if you modify the `block` it points in your deque then the value will change.
    //If you delete it then you will have a segmenant fault.
    //--- Don't Do: while (!dq.empty()) { dq.pop_back(); } ---//

    for (size_t i = 0; i < vit.size(); i++)
    {
        cout << *vit[i];
    }

    system("pause");
    return 0;
}

However, if you want to preserve that value of that iterator after it has been changed/deleted you may want to create a copy of each iterator and store the copy rather than the actual iterator

AK_
  • 1,879
  • 4
  • 21
  • 30
  • _'... after it has been changed/deleted you may want to ...'_ and what's the notification mechanism please?? – πάντα ῥεῖ Jun 13 '14 at 18:59
  • It really depends what do you want to do and how you want to do it. You may want to override pop_back() function for example to notify you then call the usual pop_back() – AK_ Jun 13 '14 at 21:11