2

items in std::vector are dynamically allocated and their addresses may change when a reallocation happens. So, it is not possible to depend on their addresses because it is not stable.

On the other hand, if I have a std::vector which contains some items and I do not have any intention to change anything about it during its life cycle, is it valid (well-defined) to use the addresses of its items?

Example:

std::vector<foo> foos;
foos.reserve(100);
for(size_t i=0;i<100;++i){
    foos.emplace_back(make_random_foo());
}
//From now no one can touch foos    
auto ptr_to_the_fifth_foo=&foos[4];

In other words, does the standard guarantee that noting will affect the vector items addresses since I did not do that by my self?

Humam Helfawi
  • 19,566
  • 15
  • 85
  • 160

2 Answers2

3

If no member function of the std::vector is called, the vector may not be changed at all and as such the contents remain the same and all pointers stay valid.

In your example you call operator[](size_type n) which is defined in the standard as being equivalent to *(a.begin() + n).

A std::vector is a container and therefore, the container requirements hold which state:

Unless otherwise specified (either explicitly or by defining a function in terms of other functions), invoking a container member function or passing a container as an argument to a library function shall not invalidate iterators to, or change the values of, objects within that container.

Since begin() is not specified to invalidate any iterators to the container, operator[] won't either.

Pixelchemist
  • 24,090
  • 7
  • 47
  • 71
1

Yes.

Pointers and references to elements are only invalidated when their iterator is invalidated.

Iterators are invalidated when capacity has to grow (when size passes capacity), or when you insert/remove elements before that element in the vector. They can also be invalidated when a container is moved-to or moved-from, but it might not occur.

I believe swap is specified to not invalidate iterators, but rather make them refer to the "new home" as it where (and hence, the pointers/references to the "new home" in the "new vector") (ie, the buffer ownership changes). Move-assign does not make this promise. I do not remember off the top of my head if move-construct does.

Yakk - Adam Nevraumont
  • 262,606
  • 27
  • 330
  • 524
  • 1
    http://stackoverflow.com/a/25348988/1938348 move should too preserve iterators, this is not jet official but when it pass it will be retroactive applied to C++11 too because it was consider as "defects". – Yankes Mar 20 '16 at 15:23
  • @Yankes the proposed resolution does not cover assignment, just construction? – Yakk - Adam Nevraumont Mar 20 '16 at 15:24
  • 1
    "no move constructor (or move assignment [...])" in http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#2321 – Yankes Mar 20 '16 at 15:43