问题
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
回答1:
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
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:
- Problem with invalidation of STL iterators when calling erase
- C++ deque: when iterators are invalidated
回答2:
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
来源:https://stackoverflow.com/questions/24210488/storing-iterators-of-stddeque