user3025945 - 1 month ago 4
C++ Question

# C++ vector values keep changing?

This is a real simple problem. I'm writing a sliding block puzzle game for an exercise.

``````1, 1, 1, 1, 1,
1, 0, 3, 4, 1,
1, 0, 2, 2, 1,
1, 1, 1, 1, 1,
``````

It receives input as in the form above, with '0' representing empty spaces, '1' representing walls, and all other numbers representing blocks.

Here is the class definition and constructor for the game state:

``````class GameState {

public:
GameState(int hght, int wdth);
GameState(const GameState &obj);
~GameState();
int getHeight();
int getWidth();
int getElem(int i, int j);
void setElem(int i, int j, int val);
void display();
bool checkSolved();
map<int, vector<int*> > blockLocations;
vector<int> blockList;
void getBlockLocations();
void findBlock(int n);
private:
int **grid;
int height, width;
void allocate() {
grid = new int*[height];
for(int i = 0; i < height; i++)
{
grid[i] = new int[width];
}
}
};

GameState::GameState(int hght, int wdth) {
height = hght;
width = wdth;
allocate();
for(int i = 0; i < hght; i++) {
for (int j = 0; j < wdth; j++) {
grid[i][j] = 0;
}
}
};
``````

Essentially, the grid is represented by a two-dimensional pointer array of integers.
`height`
and
`width`
are self-explanatory;
`blockLocations`
is a map that maps a block number to its point-wise coordinates of the form (y, x). For the time being, if a block occupies multiple spaces only the lowest rightmost space is listed. The matrix initializes as being nothing but zeros; the actual values are read in from a csv.

All of these methods are defined, but the two methods of concern are
`getBlockLocations()`
and
`findBlock(int n)`
.

``````void GameState::getBlockLocations() {
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
blockList.push_back(grid[i][j]);
int pos[2] = {i, j};
vector<int*> v;
v.push_back(pos);
blockLocations[grid[i][j]] = v;
}
}
}

void GameState::findBlock(int n) {
vector<int>::iterator it;
it = find(blockList.begin(), blockList.end(), n);
if (it != blockList.end()) {
vector<int*> * posList = &blockLocations[n];
for (int itr = 0; itr < posList->size(); itr++) {
vector<int*> curPos = *posList;
cout << curPos[itr][0] << ", " << curPos[itr][1] << endl;
}
}
}
``````

The problem comes up when I actually run this. As a case example, when I run
`getBlockLocations()`
, it correctly stores the coordinate for '2' as (2, 3). However, when I ask the program to display the location of that block with
`findBlock(2)`
, the resulting output is something along the lines of (16515320, 0). It's different every time but never correct. I don't see the pointer mistake I'm making to get incorrect values like this.

`````` for (int j = 0; j < width; j++) {
blockList.push_back(grid[i][j]);
int pos[2] = {i, j};
vector<int*> v;
v.push_back(pos);
blockLocations[grid[i][j]] = v;
}
``````

You create a `pos` variable locally and store its reference. When you go out of scope of the `for` loop it is invalid / data can be replaced by something else.

(actually as Barmar pointed out, since the `pos` address is always the same within the loop, the values change at each iteration)

You could use a `std::pair<int,int>` to store your values instead. When you insert the pair in the vector, the data is copied, not only the pointer: it is safe.

``````typedef std::pair<int,int> IntIntPair;

IntIntPair pos(i,j);
std::vector<IntIntPair> v;
``````
Source (Stackoverflow)