Chapter 6. Invalid Pointers, References, and Iterators

Consider the following code example:

vector<int> v;

// Add some elements
for(int i=0; i<10; ++i)
  v.push_back(i);

int* my_favorite_element_ptr = &v[3];
cout << "My favorite element = " << (*my_favorite_element_ptr) << endl;
cout << "Its address = " <<  my_favorite_element_ptr  << endl;

cout << "Adding more elements…"<< endl;

// Adding more elements
for(int i=0; i<100; ++i)
  v.push_back(i*10);

cout << "My favorite element = " << (*my_favorite_element_ptr) << endl;
cout << "Its address = " <<  &v[3]  << endl;

What’s going on here? We create a vector containing 10 elements, and for some reason decide to save for later a pointer to element with index 3. Then we add more elements to the vector and try to reuse the pointer we’ve acquired before. What is wrong with this code? Let’s look at the output it produces:

My favorite element = 3 Its address = 0x1001000cc
Adding more elements
…
My favorite element = 3
Its address = 0x10010028c

Note that after we add more elements to the vector, the address of the element &v[3] has changed! The problem is that when we add new elements to the vector, the existing elements might move to a totally different location.

Here is how such code works. When we create a vector, it allocates by default some number of elements (usually about 16). Then if we try to add more elements than the capacity allows, the vector allocates a new, larger array, copies existing elements from the old location to a new one, and continues ...

Get Safe C++ now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.