Problems with vectors and pointers

Hello,
Here's the code:
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
struct object_t
{
   int n;
   // ...
};

struct action_t
{
   // ...
};



struct pair_t
{
   vector<action_t> actions;
   object_t *object; // points to data[something]
};



vector<object_t> objects;
vector<pair_t> data;


//
// Removes an entry from 'vector<pair_t> data' if pairt_t::object doesn't point to any of 'vector<object_t> objects' objects
//
//EDIT: This function should erase invalid elements from data vector
// but it doesn't work (my brain too)
void sync_vectors()
{
  bool found=false;

  for(int i=0;i<data.size();i++)
    {
       for(int j=0;j<objects.size();j++)
         {
             if(data[i].object==&objects.at(j)); // compare adrsseses
                     found=true; 

        }

        if(found==false) 
          {
              data.erase(data.begin()+i);
          }
        else found=false;

    }


}


int main()
{
for(int i=0;i<10;i++)
  {
      object_t tmp;
      tmp.n=i;
      objects.push_back(tmp);

      pair_t ptmp;
      ptmp.object=&objects[i]; 
      data.push_back(ptmp);
  }

objects.erase(objects.begin()+5);

sync_vectors();


for(int i=0;i<data.size();i++)
      cout <<data[i].object->n<<endl;



}

So I have two vectors 'objects' and 'data'. First I create the 'objects' vector. The I create 'data' vector, which keeps pointers to 'objects' vector. At some specific moment I want to access objects from data. But the problem is that sometimes I need to erase some elements from 'objects' and then 'data_t::object' points to deleted objects.

How can I solve this?

Thanks for help.
Last edited on
Why do you need a vector of pointers that point to the objects stored in a different vector? Is it to keep them in a specific order without re-sorting the vector?
Is it to keep them in a specific order without re-sorting the vector?

yes.
The problem is that both vectors are sorted but by specific requirements independently of each other ('data' vector is more important here)
If you can obtain the element that holds the pointer to the object you need to free using the pointer vector sorting criterion, you can use a binary search to find it. Otherwise, you'll have to use a linear search each time you want to erase an element.
Maybe there's a way to solve this without using pointers?
If not, how can I fix the sync_vectors() function?
I think the problem with sync_vectors is that you look at a position, say '4', and if not found in the objects vector, you erase the entry at position 4. This causes everything in subsequent positions to shift down (position 5->4, 6->5, etc). Then you increment i to point to '5', thereby never checking the object that is now at position 4. The solution is to move the 'i++' to the 'else' block.

Of course, This isn't quite an optimal solution, and given a large enough data set, could be time consuming. It's an interesting problem - I would think a solution might be to have the object wrapped in some sort of custom smart pointer that keeps track of other vectors referencing it. Then it could delete from those vectors when the object is deleted. But for your purposes may be overkill, if it would even work :)

--Rollie
I was thinking and found an alternative:
Assign an unique identifier to each object. The I would be able to get an object by unique identifier:
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
61
62
63
64
65
66
67
68
69
70
71
72
struct object_t
{
   int n;
   unsigned uid; // unique identifier
   // ...
};

struct action_t
{
   // ...
};



struct pair_t
{
   action_t action;
   unsigned object_uid;
};


vector<object_t> objects;
vector<pair_t> data;


object_t *get_object_by_uid(unsigned uid)
{
   for(int i=0;i<objects.size();i++)
     {
         if(objects[i].uid==uid)
             return &objects[i];
     }
return 0;
}



void remove_bad_entries()
{
   for(int i=0;i<data.size();i++)
       if(get_object_by_uid(data[i].object_uid)==0)
           data.erase(data.begin()+i);
}


int main()
{
srand(time(0));

for(int i=0;i<10;i++)
  {
      object_t tmp;
      tmp.n=i;
      tmp.uid=rand();
      objects.push_back(tmp);

      pair_t ptmp;
      ptmp.object_uid=objects[i].uid;
      data.push_back(ptmp);
  }

objects.erase(objects.begin()+5);

remove_bad_entries(); // I know that I can remove this function.



for(int i=0;i<data.size();i++)
      cout <<get_object_by_uid(data[i].object_uid)->n<<endl;


}

And it works!
I'll pretend to be jsmith for this post.

Boost-MultiIndex could be of help -> http://www.boost.org/doc/libs/1_43_0/libs/multi_index/doc/index.html
Thanks.
If you do insist on implementing your own solution, like above, consider at least encapsulating the internals in a class and providing an interface to the user. That way you can enforce invariants.
Topic archived. No new replies allowed.