Home > Software engineering >  Is using std::span into an std::vector after push_back is called undefined behavior
Is using std::span into an std::vector after push_back is called undefined behavior

Time:10-21

My understanding of std::span is that it is essentially contains pointer into a container, a size, and some useful member functions.

template<typename T>
class SimpleSpan {
    T* ptr;
    size_t length;
    // some member functions
}

I can take a span of a vector as seen in this question.

If I add entries to the end of a vector, the vector may need to be resized. When the vector is resized, the following steps occur (order not important).

  1. A new array is allocated on the heap with more space.

  2. The entries from the vector are moved to the new array.

  3. The member ptr of the vector to the vector's array is changed to the start of the new array.

  4. The old array is deallocated.

Does anything happen to a span if the vector's array needs to be reallocated and made larger? Is using a span into a vector after push_back is called on the vector undefined behavior?

CodePudding user response:

My understanding of std::span is that it is essentially contains pointer into a container, a size, and some useful member functions.

That's not quite correct. std::span completely ignores where the data lives. It handles just the data itself. The nature (and even notion) of the data belonging to a container is completely erased away. All it cares about is that the data is contiguous in memory.

So if a vector ever resizes, which can happen during a push_back(). It's possible that the data is moved to a different memory location, invalidating any pointers pointing to it. This in turn, invalidates any std::span referring to that data.

CodePudding user response:

Documentation on push_back reads:

If the new size() is greater than capacity() then all iterators and references (including the past-the-end iterator) are invalidated. Otherwise only the past-the-end iterator is invalidated.

There is your answer right there: If the vector had to be resized, your access through an old span would be invalid. If it hadn't, it wouldn't.

  • Related