Map<vector<vector<int*>*>>

I am very curious why the following code compiles and yet does not produce a map of the expected values. I would expect the output to contain a vector of references to rows which can be accessed by an int from the row in column 2. In other words, I expected to map values in column two to their rows. However, any time something is added to the map, all of the pointers end up the same reference. Please let me know what the error is. Thanks very much.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include<iostream>
#include<vector>
#include<map>

using namespace std;

int main()
{
  vector<vector<int*>> rowss;
  auto rows = &rowss;
  rows->resize(5);
  for(int i = 0; i < 5; ++i)
    {
      rows->at(i).resize(5);
      for(int j = 0; j < 5; ++j)
      {
         rows->at(i)[j] = new int(i);
      }
    }
  cout<<"Filled."<<endl;
  cout<<"table is now: "<<endl;
  for(auto i : *rows)
    {
        for(auto j : i)
         {
            cout<<*j<<' ';
         }
        cout<<'\n';
    }
  
  map<int, vector<vector<int*>*> > * bst;
  bst = new map<int,vector<vector<int*>*> >;
  int col_idx = 2;
  for(auto i : *rows)
    {
        if(bst->find(*i[col_idx])==bst->end())
         {
            vector<vector<int*>*> vec;
            bst->insert(make_pair(*i[col_idx],vec));
         }
      cout<<"adding back row: "<<endl;
      for(auto itr : i)
         cout<<*itr<<' ';
      cout<<'\n';
      
      bst->at(*i[col_idx]).push_back(&i);
      
      cout<<"table is now: "<<endl;
      for(auto _i : *bst)
        {
            for(auto j : _i.second)
              {
                 for(auto k : *j)
                    cout<<*k<<' ';
                 cout<<'\n';
               }
        }
       cout<<'\n';
    }
}
Last edited on
On line 34, i is a copy of an element in *rows. On line 46, you add a pointer to that copy to a vector in the map. Each iteration of the loop, i will be a local copy of an element in *rows. Technically, that pointer is invalidated every iteration of the loop, so previous pointers to i inserted into the map are invalid and dereferencing them results in undefined behavior. Make line 34: for (auto& i : *rows)

(And get rid of your gratuitous use of new without a corresponding delete and the unnecessary pointers.)

Last edited on
Wow! Thank you! This has been puzzling me for so long!
Why on earth would a that loop return a local copy? I thought it would use iterators of rows or something along those lines.

(and the more than gratuitous use of new was done to mimic a larger project in which this bug came about)
Last edited on
Why on earth would a that loop return a local copy?

If you don't specifically ask for a reference in a declaration/definition, you will always get a non-reference type.

for (auto i : *rows)
is the same as:
for (vector<int*> i : *rows)

whereas:
for (auto& i: *rows)
is the same as:
for (vector<int*>& i: *rows)
Topic archived. No new replies allowed.