1

I am struggling a bit to understand the best way to safely store a reference or pointer to an item in a container without risking that the pointer could get invalidated.

With std::vector this seems like a bad idea in general, since you never know when your item might be moved to a new memory location as vector re-allocates. Is there such a way?

With list and deque is this instead a better option? From what I understand, items in these collections are not moved around, so could I just take a pointer to the memory address of a specific element?

I'm coming from Objective-C where this sort of thing is easy and common with all its containers since Objective-C pretty much uses pointers for everything so tossing them around and copying them is quite commonplace.

johnbakers
  • 24,158
  • 24
  • 130
  • 258

3 Answers3

3

For a std::vector, you can use the reserve member function to ensure that a contiguous block of memory is preallocated for the maximum number of elements you require. This means that the elements are not copied around unless you exceed the reserved capacity.

All pointers to elements in a std::deque are also invalidated when inserting or erasing elements. However, a std::list is guaranteed not to invalidate any pointers in these situations other than the pointer to the element you are erasing.

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • beautiful, so for utmost safety when independently storing pointers to items in a container, this is a major advantage to `list` sounds like. – johnbakers May 08 '13 at 11:59
  • 1
    @Fellowshee Yes, but also consider other properties of these containers such as the complexity of operations. There might be more important reasons to prefer a `std::vector`. – Joseph Mansfield May 08 '13 at 12:01
  • It occurs to me just now that I could use any container class I want, if I instead store a `unique_ptr` instead of the actual object, right? – johnbakers May 08 '13 at 14:46
  • @Fellowshee Yes. Although a `unique_ptr` is unique, so I suppose you want a `shared_ptr` instead. – Joseph Mansfield May 08 '13 at 15:18
  • If I want my container to own the object and be responsible for it, `unique_ptr` should be a good choice. It is perfectly fine to have other pointers to an object pointed at by `unique_ptr` as long as you realize those other pointers could at some point be invalidated, i.e. you understand those pointers do not own what they are pointing at. – johnbakers May 09 '13 at 00:41
0

Lists are sequence containers that allow you to insert and erase anywhere and iterate in both directions. The main drawback of lists compared to the vectors is that they lack direct access to the elements by their position.

Deques are sequence containers as well. They come with dynamic sizes that can be expanded or contracted on both ends. They are quite similar to vector and provide you direct access to the elements by their position.

You need to ask yourself: what kind of operations do I need to do on the container ?

Note that list and forward_list preserves validity of the container when manipulated, whereas deque invalidates it.

Visit http://www.cplusplus.com/ for more information about containers in c++.

Francis.Beauchamp
  • 1,323
  • 15
  • 28
0

The solution is to have the vector hold pointers to the objects rather than having it directly contain the objects. Then you don't have to be concerned about the vector resizing because when it resizes, the objects will remain at their original location in memory.

Sildoreth
  • 1,883
  • 1
  • 25
  • 38