Reputation: 9901
Say I have an object:
struct Foo
{
int bar_;
Foo(int bar) bar_(bar) {}
};
and I have an STL container that contains Foo
s, perhaps a vector, and I take
// Elsewhere...
vector<Foo> vec;
vec.push_back(Foo(4));
int *p = &(vec[0].bar_)
This is a terrible idea, right?
The reason is that vector
is going to be storing its elements in a dynamically allocated array somewhere, and eventually, if you add enough elements, it will have to allocate another array, copy over all the elements of the original array, and delete the old array. After that happens, p
points to garbage. This is why many operations on a vector
will invalidate iterators.
It seems like it would be reasonable to assume that an operation that would invalidate iterators from a container will also invalidate pointers to data members of container elements, and that if an operation doesn't invalidate iterators, those pointers will still be safe. However, many reasonable assumptions are false. Is this one of them?
Upvotes: 4
Views: 1269
Reputation: 137940
The standard specifies when such pointers are invalidated. References into a vector
die when you increase its size past capacity
or add/remove a preceding element. References into a deque
are invalidated if you add/remove from the middle.
Otherwise, references and iterators are safe to keep for the lifespan of the underlying object.
Upvotes: 11
Reputation: 2158
Yep, your instincts are correct. Where the standard mentions that an iterator is invalidated, it also tends to state that references are invalidated too.
For example, here's some partial text describing some of the effects of vector's "reserve" member function:
Notes:
Reallocation invalidates all the references, pointers, and iterators
referring to the elements in the sequence.
I can't imagine any member functions of any container that would invalidate an iterator to particular elements, but not pointers or references to those same elements, but I suppose I could be mistaken.
Best to check what the standard says for your particular container and member function.
Upvotes: 1
Reputation: 14061
Your assumption is reasonable for the vector, because an iterator can be implemented as a thin wrapper around a pointer. As an alternative to pointers, you can store offsets to a vector. These would be invalidated by insertion and erasure, but not by memory reallocation.
Upvotes: 0
Reputation:
If the vector is resized, the contents will effectively be recreated by copying and/or assignment. The new contained objects will (probably) be at different locations, and so any pointers to the, or to their members will (probably) be invalidated - you should certainly assume that this is the case.
Upvotes: 1