Search code examples
c++slicestdvectorreference-type

How do I construct a subrange of vector by reference?


I am currently utilizing the range constructor of std::vector to create another vector of a given subrange.

std::vector<int> myVect { 1, 2, 3, 4 };

std::vector<int> subrangeVector(myVect.begin(), myVect.begin() + 2);

However, this results in the ranged values of myVect being copied and taking up additional memory. This is something that is undesirable when working withing limited memory and/or with very large element types.

How do I construct a subrange of another vector by reference?

A simplified explanation of my objective is as follows:

void fun(std::vector<int> & v) { v.at(0) = 1; }

int main()
{
    std::vector<int> myVect { 1, 2, 3, 4 };

    std::size_t upperLimit = 5;
    std::vector<int> subrangeVector = subrangeView(myVect, upperLimit);

    fun(subrangeVector);  // so myVect.at(0) == 1

    return 0;
}

This would be implemented in many different functions that utilize std::vector as a parameter. I do not want to pass iterators as discussed here. Assume that I have no control over the function fun.


Solution

  • A C++ vector is a type which "owns" its memory - it cannot be a "reference type" into another vector's data.

    Instead, you will likely find a span useful: A span is a class representing contiguous data in memory - just like a vector; but - it is a "reference type", and it is not owning - just what you wanted to have. It behaves like a vector w.r.t. iteration, operator[], and so on.

    In your case, you would write:

    std::vector<int> myVect { 1, 2, 3, 4 };
    auto subrange { std::span{myVect}.subspan(0, 2); }
    

    and then use subrange just as you were planning to with the vector.

    PS: This is C++20 code, since C++17 doesn't have spans yet; if you're using earlier C++ versions, use gsl::span from the Guidelines Support Library (e.g. from here).