FY Gamer
FY Gamer

Reputation: 297

C++: struct pointer in map structure

I declared a struct like this, and the following data structures

struct piece{
  int start, height, end;

  piece(int a, int b, int c){
    start = a;  height = b; end = c;
  }

};

vector<piece> piecesTog;
map <int,piece*> data;

Then, when I read the elements I do this:

while(scanf("%d %d %d", &aux1, &aux2, &aux3) != EOF){
    piecesTog.push_back( piece(aux1, aux2, aux3) );
    data[a] = data[c] = &piecesTog[tam];
}

Well, until now, I have had no problem. However, later in the program, I have to use the piece* part, to do so, I use an iterator like this

 for(map< int, piecesTog* >::iterator it = data.begin(); it != data.end(); it++){
    piece* aux = it->second;
    ...
 }

I want to have access to the structure that the it->second points, but I tried everything and nothing worked.

I printed the memory adress of it->second and &piecesTog[tam] and they are the same, but when I do (*aux).height or it->second->height they give number completely crazy, probably some trash.

I have no clue why that is happening.

If anyone has any idea how to fix it, I would appreciate it.

Upvotes: 1

Views: 478

Answers (1)

user4581301
user4581301

Reputation: 33932

while(scanf("%d %d %d", &aux1, &aux2, &aux3) != EOF){
    piecesTog.push_back( piece(aux1, aux2, aux3) );
    data[a] = data[c] = &piecesTog[tam];
}

is almost certainly not following the Iterator invalidation rules.

piecesTog.push_back( piece(aux1, aux2, aux3) );

can trigger a resize which typically creates a new datastore, copies the elements from the old data store to the new one and then deletes the old datastore, leaving the pointers cached by

data[a] = data[c] = &piecesTog[tam];

dangling. When you use those pointers some time in the future, Ka-Blammo! Undefined Behaviour and an easily identified crash if you're lucky.

Insufficient information has been provided to supply a definitive solution, but here are a few general alternatives (in order of attractiveness):

If you know ahead of time the number of pieces that will go into piecesTog, you can reserve storage to eliminate the need to resize the vector.

If elements are only added to the end of the vector and no elements are ever removed, you can store the indexes of the elements rather than pointers to them. If the ordering never changes, the indexes will always refer to the correct elements no matter how many more items are added.

If it is possible to do so, rewrite the reader to load all of the pieces into piecesTog and then build the maps.

The above options all assume that piecesTog is assembled all at once and then left alone. If your insertion is more free-form, you sort the structure or you remove elements, you'll need to use a data structure with more favourable invalidation rules such as std::list.

Upvotes: 3

Related Questions