3

I have a std::vector containing a lot of elements. As the vector is huge, I store pointers to some specific elements in another vector, to be able to access them faster. But as the vector grows, sometimes its internal container gets reallocated, causing all my pointers to become invalid.

Is there a way to know when this happens? This way I can update the pointers in the other list.

qdii
  • 12,505
  • 10
  • 59
  • 116
  • *Any* insertion invalidates iterators. However you might be able to guess based on when `std::vector::capacity()` changes, but it definitely won't be reliable. – BoBTFish Oct 01 '12 at 14:01
  • 4
    I thought one of the purpose of `reserve()` was actually to ensure that insertions would not cause such invalidation. Am I wrong? – qdii Oct 01 '12 at 14:02
  • 1
    Its hard to imagine the benefit of storing a pointer to specific elements of a vector. What is the criteria for a specific element to be stored in another vector? Are the specific elements frequently used? – andre Oct 01 '12 at 14:38
  • @ahenderson: the vector contains something like 2 millions objects. Those objects are sentences, and they have an attribute "language" to tell if they are written in French, English, Spanish, etc. Sometimes, I want to retrieve only the English ones, but I don’t want to go through the 2 millions objects. So I kept a vector of pointers to those particular ones. – qdii Oct 01 '12 at 16:21

4 Answers4

6

You shoudldn't store pointers, you should store indexes :

i.e, instead of :

var1 = &vector[0];
var2 = &vector[13];

and access *var1, *var2

you should store :

i1 = 0;
i2 = 13;

and access vector[i1], vector[i2]


Note : you should still be careful if you use modifier methods :

  • pop_back() (which makes the last position invalid)
  • erase(i) (which shifts all the indexes greater than i)
  • etc ...

(your first method had the same caveat)

LeGEC
  • 46,477
  • 5
  • 57
  • 104
4

Maybe you should have a look at boost::container::stable_vector: http://www.boost.org/doc/libs/1_51_0/doc/html/boost/container/stable_vector.html

Jens Pohl
  • 41
  • 1
  • +1: I like the idea. As I wrote in Philipp’s comment, I am still concerned about performance, and `stable_vector` doesn’t insure contiguity so my elements will not be in the same cache line when the vector is accessed. – qdii Oct 01 '12 at 14:17
1

Instead of storing the elements in the large vector directly, you could store pointers to the individual elements. So instead of a std::vector<int> you use a std::vector<int *>. Even when the vector reallocates its content, the addresses of the data itself won't change, so other pointers to it will stay valid. This, however, requires you to create each element you enter into the vector with new and then manually delete any data which is removed.

Philipp
  • 67,764
  • 9
  • 118
  • 153
  • 1
    Okay, that’s a valid solution for objects, but in my case, having all the objects in a same sequential container is important. One of the reason is performance, I want a cache line to contain as many as possible. – qdii Oct 01 '12 at 14:10
0

I apologise, I was plain wrong in my comment. N3337 23.3.6.3 vector capacity paragraph 5:

Remarks: Reallocation invalidates all the references, pointers, and iterators referring to the elements in the sequence. It is guaranteed that no reallocation takes place during insertions that happen after a call to reserve() until the time when an insertion would make the size of the vector greater than the value of capacity().

BoBTFish
  • 19,167
  • 3
  • 49
  • 76